зеркало из https://github.com/github/ruby.git
remove marshal/gtk/kconv
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@518 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
210367ec88
Коммит
0a64817fb8
|
@ -7,6 +7,8 @@
|
|||
#fcntl
|
||||
#kconv
|
||||
#md5
|
||||
#pty
|
||||
#sdbm
|
||||
#socket
|
||||
#tkutil
|
||||
#tcltklib
|
||||
|
|
|
@ -3,10 +3,12 @@ option nodynamic
|
|||
#GD
|
||||
#curses
|
||||
dbm
|
||||
gdbm
|
||||
#etc
|
||||
fcntl
|
||||
kconv
|
||||
nkf
|
||||
marshal
|
||||
md5
|
||||
sdbm
|
||||
#socket
|
||||
#tkutil
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
option nodynamic
|
||||
|
||||
#Win32API
|
||||
curses
|
||||
#dbm
|
||||
etc
|
||||
fcntl
|
||||
#gdbm
|
||||
md5
|
||||
nkf
|
||||
#pty
|
||||
#readline
|
||||
#sdbm
|
||||
socket
|
||||
#tcltklib
|
||||
#tk
|
15
ext/Setup.nt
15
ext/Setup.nt
|
@ -1,12 +1,19 @@
|
|||
option nodynamic
|
||||
#option nodynamic
|
||||
|
||||
#GD
|
||||
Win32API
|
||||
#curses
|
||||
#dbm
|
||||
#etc
|
||||
fcntl
|
||||
kconv
|
||||
#marshal
|
||||
#gdbm
|
||||
#gtk
|
||||
marshal
|
||||
md5
|
||||
nkf
|
||||
#pty
|
||||
#readline
|
||||
sdbm
|
||||
socket
|
||||
#tkutil
|
||||
#tcltklib
|
||||
#tk
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
MANIFEST
|
||||
depend
|
||||
MANIFEST
|
||||
Win32API.c
|
||||
extconf.rb
|
||||
getch.rb
|
||||
point.rb
|
|
@ -0,0 +1,231 @@
|
|||
/*
|
||||
Win32API - Ruby Win32 API Import Facility
|
||||
*/
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#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)
|
||||
rb_raise(rb_eRuntimeError, "LoadLibrary: %s\n", RSTRING(dllname)->ptr);
|
||||
Data_Wrap_Struct(self, 0, Win32API_FreeLibrary, hdll);
|
||||
}
|
||||
hproc = GetProcAddress(hdll, RSTRING(proc)->ptr);
|
||||
if (!hproc) {
|
||||
str = rb_str_new3(proc);
|
||||
str = rb_str_cat(str, "A", 1);
|
||||
hproc = GetProcAddress(hdll, RSTRING(str)->ptr);
|
||||
if (!hproc)
|
||||
rb_raise(rb_eRuntimeError, "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 = rb_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':
|
||||
rb_ary_push(a_import, INT2FIX(_T_NUMBER));
|
||||
break;
|
||||
case 'P': case 'p':
|
||||
rb_ary_push(a_import, INT2FIX(_T_POINTER));
|
||||
break;
|
||||
case 'I': case 'i':
|
||||
rb_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)
|
||||
int 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)
|
||||
rb_raise(rb_eRuntimeError, "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 = rb_ary_entry(obj_import, i);
|
||||
timport = FIX2INT(import_type);
|
||||
switch (timport) {
|
||||
case _T_NUMBER:
|
||||
case _T_INTEGER:
|
||||
lParam = NUM2INT(rb_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 = rb_ary_entry(args, i);
|
||||
Check_Type(str, T_STRING);
|
||||
rb_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 = rb_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", rb_cObject);
|
||||
rb_define_method(cWin32API, "initialize", Win32API_initialize, 4);
|
||||
rb_define_method(cWin32API, "call", Win32API_Call, -1);
|
||||
rb_define_alias(cWin32API, "Call", "call");
|
||||
}
|
||||
|
||||
void
|
||||
Init_win32api()
|
||||
{
|
||||
Init_Win32API();
|
||||
}
|
|
@ -1 +1 @@
|
|||
Win32API.o : Win32API.c $(hdrdir)/ruby.h $(hdrdir)/config.h $(hdrdir)/defines.h
|
||||
Win32API.o : Win32API.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
case PLATFORM
|
||||
when /cygwin/,/mingw/
|
||||
$CFLAGS = "-fno-defer-pop"
|
||||
create_makefile("Win32API")
|
||||
when /win32/
|
||||
create_makefile("Win32API")
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
require 'Win32API'
|
||||
|
||||
getch = Win32API.new("crtdll", "_getch", [], 'L')
|
||||
|
||||
puts getch.Call.chr
|
|
@ -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
|
|
@ -1,73 +0,0 @@
|
|||
#! /usr/local/bin/ruby
|
||||
|
||||
def older(file1, file2)
|
||||
if !File.exist?(file1) then
|
||||
return TRUE
|
||||
end
|
||||
if !File.exist?(file2) then
|
||||
return FALSE
|
||||
end
|
||||
if File.mtime(file1) < File.mtime(file2)
|
||||
return TRUE
|
||||
end
|
||||
return FALSE
|
||||
end
|
||||
|
||||
target = ARGV.shift
|
||||
unless target =~ /\.so/
|
||||
STDERR.printf "wrong suffix specified\n"
|
||||
exit 1
|
||||
end
|
||||
base = File.basename(target, ".so")
|
||||
entry="Init_#{base}"
|
||||
ldargs = "-e#{entry} -bI:../ruby.imp -bM:SRE -T512 -H512 -lc"
|
||||
|
||||
def uniq(data)
|
||||
last=nil
|
||||
data.delete_if do |name|
|
||||
if last == name
|
||||
TRUE
|
||||
else
|
||||
last = name
|
||||
FALSE
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def extract(nm, out)
|
||||
data = nm.readlines.collect{|line|
|
||||
line = line.split
|
||||
case line[1]
|
||||
when "B", "D", "T"
|
||||
line[2]
|
||||
else
|
||||
next
|
||||
end
|
||||
}.compact!.sort!
|
||||
uniq(data)
|
||||
exp = open(out, "w")
|
||||
for line in data
|
||||
exp.printf "%s\n", line
|
||||
end
|
||||
exp.close
|
||||
nm.close
|
||||
end
|
||||
if older("../ruby.imp", "../../miniruby")
|
||||
# nm = open("|/usr/ccs/bin/nm -Bex ../../*.o")
|
||||
# nm = open("|/usr/ccs/bin/nm -Bex ../../*.o")
|
||||
nm = open("|nm ../../*.o")
|
||||
extract(nm, "../ruby.imp")
|
||||
end
|
||||
|
||||
objs = Dir["*.o"].join(" ")
|
||||
#nm = open("|/usr/ccs/bin/nm -Bex #{objs}")
|
||||
nm = open("|nm #{objs}")
|
||||
extract(nm, "#{base}.exp")
|
||||
|
||||
#system format("/usr/ccs/bin/ld %s %s ",ldargs,ARGV.join(' '))
|
||||
#system "/bin/rm -f #{base}.exp"
|
||||
#system "chmod o-rwx ${base}.so"
|
||||
|
||||
p format("/usr/ccs/bin/ld %s %s ",ldargs,ARGV.join(' '))
|
||||
p "/bin/rm -f #{base}.exp"
|
||||
p "chmod o-rwx ${base}.so"
|
|
@ -0,0 +1,33 @@
|
|||
|
||||
def uniq(data)
|
||||
last=nil
|
||||
data.delete_if do |name|
|
||||
if last == name
|
||||
TRUE
|
||||
else
|
||||
last = name
|
||||
FALSE
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def extract(nm, out)
|
||||
data = nm.readlines.collect{|line|
|
||||
line = line.split
|
||||
case line[1]
|
||||
when "B", "D"
|
||||
line[0]
|
||||
else
|
||||
next
|
||||
end
|
||||
}.compact!.sort!
|
||||
uniq(data)
|
||||
exp = open(out, "w")
|
||||
exp.printf "#!\n"
|
||||
for line in data
|
||||
exp.printf "%s\n", line
|
||||
end
|
||||
exp.close
|
||||
nm.close
|
||||
end
|
||||
extract(open("|/usr/ccs/bin/nm -p ../libruby.a"), "../ruby.imp")
|
|
@ -10,6 +10,10 @@
|
|||
#else
|
||||
# ifdef HAVE_NCURSES_CURSES_H
|
||||
# include <ncurses/curses.h>
|
||||
#else
|
||||
# ifdef HAVE_CURSES_COLR_CURSES_H
|
||||
# include <varargs.h>
|
||||
# include <curses_colr/curses.h>
|
||||
# else
|
||||
# include <curses.h>
|
||||
# if (defined(__bsdi__) || defined(__NetBSD__)) && !defined(_maxx)
|
||||
|
@ -26,8 +30,11 @@
|
|||
# endif
|
||||
# endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "stdio.h"
|
||||
#include "ruby.h"
|
||||
#include "rubyio.h"
|
||||
|
||||
static VALUE mCurses;
|
||||
static VALUE cWindow;
|
||||
|
@ -350,6 +357,7 @@ static VALUE
|
|||
curses_getch(obj)
|
||||
VALUE obj;
|
||||
{
|
||||
rb_read_check(stdin);
|
||||
return CHR2FIX(getch());
|
||||
}
|
||||
|
||||
|
@ -359,6 +367,8 @@ curses_getstr(obj)
|
|||
VALUE obj;
|
||||
{
|
||||
char rtn[1024]; /* This should be big enough.. I hope */
|
||||
|
||||
rb_read_check(stdin);
|
||||
getstr(rtn);
|
||||
return rb_tainted_str_new2(rtn);
|
||||
}
|
||||
|
@ -408,11 +418,13 @@ window_s_new(class, lines, cols, top, left)
|
|||
{
|
||||
VALUE w;
|
||||
WINDOW *window;
|
||||
VALUE args[4];
|
||||
|
||||
window = newwin(NUM2INT(lines), NUM2INT(cols), NUM2INT(top), NUM2INT(left));
|
||||
wclear(window);
|
||||
w = prep_window(class, window);
|
||||
rb_obj_call_init(w);
|
||||
args[0] = lines; args[1] = cols; args[2] = top; args[3] = left;
|
||||
rb_obj_call_init(w, 4, args);
|
||||
|
||||
return w;
|
||||
}
|
||||
|
@ -428,11 +440,17 @@ window_subwin(obj, lines, cols, top, left)
|
|||
{
|
||||
struct windata *winp;
|
||||
WINDOW *window;
|
||||
VALUE w;
|
||||
VALUE args[4];
|
||||
|
||||
GetWINDOW(obj, winp);
|
||||
window = subwin(winp->window, NUM2INT(lines), NUM2INT(cols),
|
||||
NUM2INT(top), NUM2INT(left));
|
||||
return prep_window(cWindow, window);
|
||||
w = prep_window(cWindow, window);
|
||||
args[0] = lines; args[1] = cols; args[2] = top; args[3] = left;
|
||||
rb_obj_call_init(w, 4, args);
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
/* def close */
|
||||
|
@ -717,6 +735,7 @@ window_getch(obj)
|
|||
{
|
||||
struct windata *winp;
|
||||
|
||||
rb_read_check(stdin);
|
||||
GetWINDOW(obj, winp);
|
||||
return CHR2FIX(wgetch(winp->window));
|
||||
}
|
||||
|
@ -730,6 +749,7 @@ window_getstr(obj)
|
|||
char rtn[1024]; /* This should be big enough.. I hope */
|
||||
|
||||
GetWINDOW(obj, winp);
|
||||
rb_read_check(stdin);
|
||||
wgetstr(winp->window, rtn);
|
||||
return rb_tainted_str_new2(rtn);
|
||||
}
|
||||
|
|
|
@ -1,22 +1,21 @@
|
|||
require 'mkmf'
|
||||
$CFLAGS="-I/usr/include/ncurses -I/usr/local/include/ncurses"
|
||||
$LDFLAGS="-L/usr/local/lib"
|
||||
make=FALSE
|
||||
|
||||
make=false
|
||||
have_library("mytinfo", "tgetent") if /bow/ =~ PLATFORM
|
||||
if have_header("ncurses.h") and have_library("ncurses", "initscr")
|
||||
make=TRUE
|
||||
make=true
|
||||
elsif have_header("ncurses/curses.h") and have_library("ncurses", "initscr")
|
||||
make=TRUE
|
||||
make=true
|
||||
elsif have_header("curses_colr/curses.h") and have_library("cur_colr", "initscr")
|
||||
make=true
|
||||
else
|
||||
$CFLAGS=nil
|
||||
have_library("termcap", "tgetent")
|
||||
if have_library("curses", "initscr")
|
||||
make=TRUE
|
||||
make=true
|
||||
end
|
||||
end
|
||||
|
||||
if make then
|
||||
if make
|
||||
for f in %w(isendwin ungetch beep doupdate flash deleteln wdeleteln)
|
||||
have_func(f)
|
||||
end
|
||||
|
|
|
@ -12,6 +12,9 @@
|
|||
|
||||
#include "ruby.h"
|
||||
|
||||
#ifdef HAVE_CDEFS_H
|
||||
# include <cdefs.h>
|
||||
#endif
|
||||
#include <ndbm.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
@ -84,7 +87,7 @@ fdbm_s_open(argc, argv, klass)
|
|||
obj = Data_Make_Struct(klass,struct dbmdata,0,free_dbm,dbmp);
|
||||
dbmp->di_dbm = dbm;
|
||||
dbmp->di_size = -1;
|
||||
rb_obj_call_init(obj);
|
||||
rb_obj_call_init(obj, argc, argv);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
@ -329,7 +332,7 @@ fdbm_store(obj, keystr, valstr)
|
|||
dbmp->di_size = -1;
|
||||
dbm = dbmp->di_dbm;
|
||||
if (dbm_store(dbm, key, val, DBM_REPLACE)) {
|
||||
#ifdef HAVE_DBM_CLAERERR
|
||||
#ifdef HAVE_DBM_CLEARERR
|
||||
dbm_clearerr(dbm);
|
||||
#endif
|
||||
if (errno == EPERM) rb_sys_fail(0);
|
||||
|
|
|
@ -1 +1 @@
|
|||
dbm.o: dbm.c $(hdrdir)/ruby.h $(hdrdir)/config.h $(hdrdir)/defines.h
|
||||
dbm.o: dbm.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
require 'mkmf'
|
||||
$LDFLAGS = "-L/usr/local/lib"
|
||||
dir_config("dbm")
|
||||
have_library("gdbm", "dbm_open") or
|
||||
have_library("db", "dbm_open") or
|
||||
have_library("dbm", "dbm_open")
|
||||
if have_func("dbm_open")
|
||||
have_header("cdefs.h")
|
||||
if have_header("ndbm.h") and have_func("dbm_open")
|
||||
have_func("dbm_clearerr")
|
||||
create_makefile("dbm")
|
||||
end
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
MANIFEST
|
||||
etc.c
|
||||
etc.doc
|
||||
etc.txt
|
||||
etc.txt.jp
|
||||
depend
|
||||
extconf.rb
|
||||
|
|
|
@ -1 +1 @@
|
|||
etc.o : etc.c $(hdrdir)/ruby.h $(hdrdir)/config.h $(hdrdir)/defines.h
|
||||
etc.o : etc.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
|
||||
|
|
|
@ -125,7 +125,7 @@ static VALUE
|
|||
etc_passwd(obj)
|
||||
VALUE obj;
|
||||
{
|
||||
#if defined(HAVE_GETPWENT)
|
||||
#ifdef HAVE_GETPWENT
|
||||
struct passwd *pw;
|
||||
|
||||
if (rb_iterator_p()) {
|
||||
|
@ -136,12 +136,11 @@ etc_passwd(obj)
|
|||
endpwent();
|
||||
return obj;
|
||||
}
|
||||
pw = getpwent();
|
||||
if (pw == 0) rb_raise(rb_eRuntimeError, "can't fetch next -- /etc/passwd");
|
||||
return setup_passwd(pw);
|
||||
#else
|
||||
return Qnil;
|
||||
if (pw = getpwent()) {
|
||||
return setup_passwd(pw);
|
||||
}
|
||||
#endif
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
#ifdef HAVE_GETGRENT
|
||||
|
@ -214,10 +213,11 @@ etc_group(obj)
|
|||
endgrent();
|
||||
return obj;
|
||||
}
|
||||
return setup_group(getgrent());
|
||||
#else
|
||||
return Qnil;
|
||||
if (grp = getgrent()) {
|
||||
return setup_group(grp);
|
||||
}
|
||||
#endif
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
static VALUE mEtc;
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
.\" etc.doc - -*- Indented-Text -*- created at: Fri Jul 14 00:47:15 JST 1995
|
||||
|
||||
** Etc(Module)
|
||||
|
||||
The module to retrieve information under /etc directory. Available
|
||||
only on UNIX platforms. All operations defined in this module are
|
||||
module functions, so that you can include Etc module into your class.
|
||||
|
||||
Module Function:
|
||||
|
||||
getlogin
|
||||
|
||||
returns login name of the user. It this fails, try getpwuid().
|
||||
|
||||
getpwnam(name)
|
||||
|
||||
searches in /etc/passwd file (or equivalent database), and
|
||||
returns password entry for the user. The return value is an
|
||||
passwd structure, which has members described below.
|
||||
|
||||
struct passwd
|
||||
name # user name(string)
|
||||
passwd # encrypted password(string)
|
||||
uid # user ID(integer)
|
||||
gid # group ID(integer)
|
||||
gecos # gecos field(string)
|
||||
dir # home directory(string)
|
||||
shell # login shell(string)
|
||||
# members below are optional
|
||||
change # password change time(integer)
|
||||
quota # quota value(integer)
|
||||
age # password age(integer)
|
||||
class # user access class(string)
|
||||
comment # comment(string)
|
||||
expire # account expiration time(integer)
|
||||
end
|
||||
|
||||
See getpwnam(3) for detail.
|
||||
|
||||
getpwuid([uid])
|
||||
|
||||
returns passwd entry for the specified user id. If uid is
|
||||
ommitted, use the value from getuid(). See getpwuid(3) for
|
||||
detail.
|
||||
|
||||
getgrgid(gid)
|
||||
|
||||
searches in /etc/group file (or equivalent database), and
|
||||
returns group entry for the group id. The return value is an
|
||||
group structure, which has members described below.
|
||||
|
||||
struct group
|
||||
name # group name(string)
|
||||
passwd # group password(string)
|
||||
gid # group ID(integer)
|
||||
mem # array of the group member names
|
||||
end
|
||||
|
||||
See getgrgid(3) for detail.
|
||||
|
||||
getgrnam(name)
|
||||
|
||||
returns the group entry for the specified name. The return
|
||||
value is the group structure. See getgrnam(3) for detail.
|
||||
|
||||
group
|
||||
|
||||
iterates over all group entries.
|
||||
|
||||
passwd
|
||||
|
||||
iterates over all passwd entries.
|
|
@ -5,8 +5,7 @@
|
|||
/etcディレクトリ以下の情報を得るためのモジュール.クラスにインクルード
|
||||
して使うこともできる.
|
||||
|
||||
Methods:
|
||||
Single Methods:
|
||||
Module Function:
|
||||
|
||||
getlogin
|
||||
|
608
ext/extmk.rb.in
608
ext/extmk.rb.in
|
@ -1,43 +1,40 @@
|
|||
#! /usr/local/bin/ruby
|
||||
|
||||
$".push 'mkmf.rb' #"
|
||||
load '@top_srcdir@/lib/find.rb'
|
||||
$".push 'mkmf.rb'
|
||||
|
||||
if ARGV[0] == 'static'
|
||||
$force_static = TRUE
|
||||
$force_static = true
|
||||
ARGV.shift
|
||||
elsif ARGV[0] == 'install'
|
||||
$install = TRUE
|
||||
$install = true
|
||||
$destdir = ARGV[1] || ''
|
||||
ARGV.shift
|
||||
elsif ARGV[0] == 'clean'
|
||||
$clean = TRUE
|
||||
$clean = true
|
||||
ARGV.shift
|
||||
end
|
||||
|
||||
SRC_EXT = ["c", "cc", "m", "cxx", "cpp", "C"]
|
||||
$extlist = []
|
||||
|
||||
$cache_mod = FALSE;
|
||||
$includedir = "@includedir@".gsub(/\$\{prefix\}|\$\(prefix\)/,'@prefix@')
|
||||
|
||||
$cache_mod = false
|
||||
$lib_cache = {}
|
||||
$func_cache = {}
|
||||
$hdr_cache = {}
|
||||
$top_srcdir = "@top_srcdir@"
|
||||
if $top_srcdir !~ "^/"
|
||||
# get absolute path
|
||||
save = Dir.pwd
|
||||
Dir.chdir $top_srcdir
|
||||
$top_srcdir = Dir.pwd
|
||||
Dir.chdir save
|
||||
$top_srcdir = File.expand_path($top_srcdir)
|
||||
end
|
||||
$topdir = ".."
|
||||
if $topdir !~ "^/"
|
||||
# get absolute path
|
||||
save = Dir.pwd
|
||||
Dir.chdir $topdir
|
||||
$topdir = Dir.pwd
|
||||
Dir.chdir save
|
||||
end
|
||||
$dots = if "@INSTALL@" =~ /^\// then "" else "#{$topdir}/ext/" end
|
||||
# get absolute path
|
||||
$topdir = File.expand_path("..")
|
||||
|
||||
$:.push $top_srcdir
|
||||
$:.push $top_srcdir+"/lib"
|
||||
|
||||
require 'find'
|
||||
|
||||
if File.exist?("config.cache") then
|
||||
f = open("config.cache", "r")
|
||||
|
@ -56,26 +53,26 @@ end
|
|||
|
||||
def older(file1, file2)
|
||||
if !File.exist?(file1) then
|
||||
return TRUE
|
||||
return true
|
||||
end
|
||||
if !File.exist?(file2) then
|
||||
return FALSE
|
||||
return false
|
||||
end
|
||||
if File.mtime(file1) < File.mtime(file2)
|
||||
return TRUE
|
||||
return true
|
||||
end
|
||||
return FALSE
|
||||
return false
|
||||
end
|
||||
|
||||
if PLATFORM == "m68k-human"
|
||||
CFLAGS = "@CFLAGS@".gsub(/-c..-stack=[0-9]+ */, '')
|
||||
if RUBY_PLATFORM == "m68k-human"
|
||||
CFLAGS = "@CFLAGS@".gsub(/-c..-stack=[0-9]+ */, '')
|
||||
else
|
||||
CFLAGS = "@CFLAGS@"
|
||||
CFLAGS = "@CFLAGS@"
|
||||
end
|
||||
LINK = "@CC@ -o conftest -I#$topdir -I#$top_srcdir -I@includedir@ #{CFLAGS} %s @LDFLAGS@ %s conftest.c @LIBS@ %s"
|
||||
CPP = "@CPP@ @CPPFLAGS@ -I#$topdir -I#$top_srcdir -I@includedir@ #{CFLAGS} %s conftest.c"
|
||||
LINK = "@CC@ -o conftest -I#$topdir -I#$top_srcdir #{CFLAGS} -I#$includedir @LDFLAGS@ %s %s conftest.c %s %s @LIBS@"
|
||||
CPP = "@CPP@ @CPPFLAGS@ -I#$topdir -I#$top_srcdir #{CFLAGS} -I#$includedir %s %s conftest.c"
|
||||
|
||||
if /cygwin|mswin32|djgpp|mingw32|m68k-human/i =~ PLATFORM
|
||||
if /cygwin|mswin32|djgpp|mingw32|m68k-human|i386-os2_emx/i =~ RUBY_PLATFORM
|
||||
$null = open("nul", "w")
|
||||
else
|
||||
$null = open("/dev/null", "w")
|
||||
|
@ -85,6 +82,7 @@ $orgerr = $stderr.dup
|
|||
$orgout = $stdout.dup
|
||||
def xsystem command
|
||||
if $DEBUG
|
||||
puts command
|
||||
return system(command)
|
||||
end
|
||||
$stderr.reopen($null)
|
||||
|
@ -95,116 +93,194 @@ def xsystem command
|
|||
return r
|
||||
end
|
||||
|
||||
def try_link(libs)
|
||||
xsystem(format(LINK, $CFLAGS, $LDFLAGS, libs))
|
||||
def try_link0(src, opt="")
|
||||
cfile = open("conftest.c", "w")
|
||||
cfile.print src
|
||||
cfile.close
|
||||
xsystem(format(LINK, $CFLAGS, $LDFLAGS, opt, $LOCAL_LIBS))
|
||||
end
|
||||
|
||||
def try_cpp
|
||||
xsystem(format(CPP, $CFLAGS))
|
||||
def try_link(src, opt="")
|
||||
begin
|
||||
try_link0(src, opt)
|
||||
ensure
|
||||
system "rm -f conftest*"
|
||||
end
|
||||
end
|
||||
|
||||
def install_rb(mfile)
|
||||
def try_cpp(src, opt="")
|
||||
cfile = open("conftest.c", "w")
|
||||
cfile.print src
|
||||
cfile.close
|
||||
begin
|
||||
xsystem(format(CPP, $CFLAGS, opt))
|
||||
ensure
|
||||
system "rm -f conftest*"
|
||||
end
|
||||
end
|
||||
|
||||
def egrep_cpp(pat, src, opt="")
|
||||
cfile = open("conftest.c", "w")
|
||||
cfile.print src
|
||||
cfile.close
|
||||
begin
|
||||
xsystem(format(CPP+"|egrep #{pat}", $CFLAGS, opt))
|
||||
ensure
|
||||
system "rm -f conftest*"
|
||||
end
|
||||
end
|
||||
|
||||
def try_run(src, opt="")
|
||||
begin
|
||||
if try_link0(src, opt)
|
||||
if xsystem("./conftest")
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
else
|
||||
nil
|
||||
end
|
||||
ensure
|
||||
system "rm -f conftest*"
|
||||
end
|
||||
end
|
||||
|
||||
def install_rb(mfile, srcdir = nil)
|
||||
libdir = "lib"
|
||||
libdir = srcdir + "/" + libdir if srcdir
|
||||
path = []
|
||||
dir = []
|
||||
Find.find("lib") do |f|
|
||||
Find.find(libdir) do |f|
|
||||
next unless /\.rb$/ =~ f
|
||||
f = f[4..-1]
|
||||
f = f[libdir.length+1..-1]
|
||||
path.push f
|
||||
dir |= File.dirname(f)
|
||||
end
|
||||
for f in dir
|
||||
next if f == "."
|
||||
mfile.printf "\t@test -d $(DESTDIR)$(pkglibdir)/%s || mkdir $(DESTDIR)$(pkglibdir)/%s\n", f, f
|
||||
mfile.printf "\t@$(RUBY) -r ftools -e 'File::makedirs(*ARGV)' $(DESTDIR)$(pkglibdir)/%s\n", f
|
||||
end
|
||||
for f in path
|
||||
mfile.printf "\t$(INSTALL_DATA) lib/%s $(DESTDIR)$(pkglibdir)/%s\n", f, f
|
||||
mfile.printf "\t@$(RUBY) -r ftools -e 'File::install(ARGV[0], ARGV[1], 0644, true)' $(srcdir)/lib/%s $(DESTDIR)$(pkglibdir)/%s\n", f, f
|
||||
end
|
||||
end
|
||||
|
||||
def append_library(libs, lib)
|
||||
if /mswin32/ =~ RUBY_PLATFORM
|
||||
lib + ".lib " + libs
|
||||
else
|
||||
"-l" + lib + " " + libs
|
||||
end
|
||||
end
|
||||
|
||||
def have_library(lib, func="main")
|
||||
if $lib_cache[lib]
|
||||
if $lib_cache[lib] == "yes"
|
||||
if $libs
|
||||
$libs = "-l" + lib + " " + $libs
|
||||
else
|
||||
$libs = "-l" + lib
|
||||
end
|
||||
return TRUE
|
||||
$libs = append_library($libs, lib)
|
||||
return true
|
||||
else
|
||||
return FALSE
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
if func && func != ""
|
||||
cfile = open("conftest.c", "w")
|
||||
cfile.printf "\
|
||||
libs = append_library($libs, lib)
|
||||
if /mswin32/ =~ RUBY_PLATFORM
|
||||
r = try_link(<<"SRC", libs)
|
||||
#include <windows.h>
|
||||
#include <winsock.h>
|
||||
int main() { return 0; }
|
||||
int t() { %s(); return 0; }
|
||||
", func
|
||||
cfile.close
|
||||
|
||||
begin
|
||||
if $libs
|
||||
libs = "-l" + lib + " " + $libs
|
||||
else
|
||||
libs = "-l" + lib
|
||||
int t() { #{func}(); return 0; }
|
||||
SRC
|
||||
unless r
|
||||
r = try_link(<<"SRC", libs)
|
||||
#include <windows.h>
|
||||
#include <winsock.h>
|
||||
int main() { return 0; }
|
||||
int t() { void ((*p)()); p = (void ((*)()))#{func}; return 0; }
|
||||
SRC
|
||||
end
|
||||
unless try_link(libs)
|
||||
$lib_cache[lib] = 'no'
|
||||
$cache_mod = TRUE
|
||||
return FALSE
|
||||
end
|
||||
ensure
|
||||
system "rm -f conftest*"
|
||||
else
|
||||
r = try_link(<<"SRC", libs)
|
||||
int main() { return 0; }
|
||||
int t() { #{func}(); return 0; }
|
||||
SRC
|
||||
end
|
||||
unless r
|
||||
$lib_cache[lib] = 'no'
|
||||
$cache_mod = true
|
||||
return false
|
||||
end
|
||||
else
|
||||
if $libs
|
||||
libs = "-l" + lib + " " + $libs
|
||||
else
|
||||
libs = "-l" + lib
|
||||
end
|
||||
libs = append_library($libs, lib)
|
||||
end
|
||||
|
||||
$libs = libs
|
||||
$lib_cache[lib] = 'yes'
|
||||
$cache_mod = TRUE
|
||||
return TRUE
|
||||
$cache_mod = true
|
||||
return true
|
||||
end
|
||||
|
||||
def find_library(lib, func, *paths)
|
||||
ldflags = $LDFLAGS
|
||||
libs = append_library($libs, lib)
|
||||
until try_link(<<"SRC", libs)
|
||||
int main() { return 0; }
|
||||
int t() { #{func}(); return 0; }
|
||||
SRC
|
||||
if paths.size == 0
|
||||
$LDFLAGS = ldflags
|
||||
return false
|
||||
end
|
||||
$LDFLAGS = ldflags + " -L"+paths.shift
|
||||
end
|
||||
$libs = libs
|
||||
return true
|
||||
end
|
||||
|
||||
def have_func(func)
|
||||
if $func_cache[func]
|
||||
if $func_cache[func] == "yes"
|
||||
$defs.push(format("-DHAVE_%s", func.upcase))
|
||||
return TRUE
|
||||
return true
|
||||
else
|
||||
return FALSE
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
cfile = open("conftest.c", "w")
|
||||
cfile.printf "\
|
||||
char %s();
|
||||
int main() { return 0; }
|
||||
int t() { %s(); return 0; }
|
||||
", func, func
|
||||
cfile.close
|
||||
|
||||
libs = $libs
|
||||
libs = "" if libs == nil
|
||||
|
||||
begin
|
||||
unless try_link(libs)
|
||||
$func_cache[func] = 'no'
|
||||
$cache_mod = TRUE
|
||||
return FALSE
|
||||
if /mswin32/ =~ RUBY_PLATFORM
|
||||
r = try_link(<<"SRC", libs)
|
||||
#include <windows.h>
|
||||
#include <winsock.h>
|
||||
int main() { return 0; }
|
||||
int t() { #{func}(); return 0; }
|
||||
SRC
|
||||
unless r
|
||||
r = try_link(<<"SRC", libs)
|
||||
#include <windows.h>
|
||||
#include <winsock.h>
|
||||
int main() { return 0; }
|
||||
int t() { void ((*p)()); p = (void ((*)()))#{func}; return 0; }
|
||||
SRC
|
||||
end
|
||||
ensure
|
||||
system "rm -f conftest*"
|
||||
else
|
||||
r = try_link(<<"SRC", libs)
|
||||
int main() { return 0; }
|
||||
int t() { #{func}(); return 0; }
|
||||
SRC
|
||||
end
|
||||
unless r
|
||||
$func_cache[func] = 'no'
|
||||
$cache_mod = true
|
||||
return false
|
||||
end
|
||||
$defs.push(format("-DHAVE_%s", func.upcase))
|
||||
$func_cache[func] = 'yes'
|
||||
$cache_mod = TRUE
|
||||
return TRUE
|
||||
$cache_mod = true
|
||||
return true
|
||||
end
|
||||
|
||||
def have_header(header)
|
||||
|
@ -212,32 +288,60 @@ def have_header(header)
|
|||
if $hdr_cache[header] == "yes"
|
||||
header.tr!("a-z./\055", "A-Z___")
|
||||
$defs.push(format("-DHAVE_%s", header))
|
||||
return TRUE
|
||||
return true
|
||||
else
|
||||
return FALSE
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
cfile = open("conftest.c", "w")
|
||||
cfile.printf "\
|
||||
#include <%s>
|
||||
", header
|
||||
cfile.close
|
||||
|
||||
begin
|
||||
unless try_cpp
|
||||
$hdr_cache[header] = 'no'
|
||||
$cache_mod = TRUE
|
||||
return FALSE
|
||||
end
|
||||
ensure
|
||||
system "rm -f conftest*"
|
||||
unless try_cpp(<<"SRC")
|
||||
#include <#{header}>
|
||||
SRC
|
||||
$hdr_cache[header] = 'no'
|
||||
$cache_mod = true
|
||||
return false
|
||||
end
|
||||
$hdr_cache[header] = 'yes'
|
||||
header.tr!("a-z./\055", "A-Z___")
|
||||
$defs.push(format("-DHAVE_%s", header))
|
||||
$cache_mod = TRUE
|
||||
return TRUE
|
||||
$cache_mod = true
|
||||
return true
|
||||
end
|
||||
|
||||
def arg_config(config, default=nil)
|
||||
unless defined? $configure_args
|
||||
$configure_args = {}
|
||||
args = "@configure_args@"
|
||||
if /mswin32/ =~ RUBY_PLATFORM and ENV["CONFIGURE_ARGS"]
|
||||
args = args + " " + ENV["CONFIGURE_ARGS"]
|
||||
end
|
||||
for arg in args.split
|
||||
next unless /^--/ =~ arg
|
||||
if /=/ =~ arg
|
||||
$configure_args[$`] = $'
|
||||
else
|
||||
$configure_args[arg] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
$configure_args.fetch(config, default)
|
||||
end
|
||||
|
||||
def with_config(config, default=nil)
|
||||
unless /^--with-/ =~ config
|
||||
config = '--with-' + config
|
||||
end
|
||||
arg_config(config, default)
|
||||
end
|
||||
|
||||
def enable_config(config, default=nil)
|
||||
if arg_config("--enable-"+config, default)
|
||||
true
|
||||
elsif arg_config("--disable-"+config, false)
|
||||
false
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
def create_header()
|
||||
|
@ -251,28 +355,54 @@ def create_header()
|
|||
end
|
||||
end
|
||||
|
||||
def create_makefile(target)
|
||||
def dir_config(target)
|
||||
dir = with_config("%s-dir"%target)
|
||||
if dir
|
||||
idir = " -I"+dir+"/include"
|
||||
ldir = " -L"+dir+"/lib"
|
||||
end
|
||||
unless idir
|
||||
dir = with_config("%s-include"%target)
|
||||
idir = " -I"+dir if dir
|
||||
end
|
||||
unless ldir
|
||||
dir = with_config("%s-lib"%target)
|
||||
ldir = " -L"+dir if dir
|
||||
end
|
||||
|
||||
if $libs and "@DLEXT@" == "o"
|
||||
$CFLAGS += idir if idir
|
||||
$LDFLAGS += ldir if ldir
|
||||
end
|
||||
|
||||
def create_makefile(target)
|
||||
$target = target
|
||||
|
||||
system "rm -f conftest*"
|
||||
if "@DLEXT@" == $OBJEXT
|
||||
libs = $libs.split
|
||||
for lib in libs
|
||||
lib.sub!(/-l(.*)/, '"lib\1.a"')
|
||||
lib.sub!(/-l(.*)/, %%"lib\\1.#{$LIBEXT}"%)
|
||||
end
|
||||
$defs.push(format("-DEXTLIB='%s'", libs.join(",")))
|
||||
end
|
||||
|
||||
$DLDFLAGS = '@DLDFLAGS@'
|
||||
|
||||
if PLATFORM =~ /beos/
|
||||
if $libs
|
||||
$libs = $libs + " -lruby"
|
||||
else
|
||||
$libs = "-lruby"
|
||||
end
|
||||
if RUBY_PLATFORM =~ /beos/
|
||||
$libs = $libs + " -lruby"
|
||||
$DLDFLAGS = $DLDFLAGS + " -L" + $topdir
|
||||
end
|
||||
|
||||
$srcdir = $top_srcdir + "/ext/" + target
|
||||
defflag = ''
|
||||
if RUBY_PLATFORM =~ /cygwin/ and not $static
|
||||
if File.exist? target + ".def"
|
||||
defflag = "--def=" + target + ".def"
|
||||
end
|
||||
$libs = $libs + " @LIBRUBYARG@"
|
||||
$DLDFLAGS = $DLDFLAGS + " -L" + $topdir
|
||||
end
|
||||
|
||||
$srcdir = $top_srcdir + "/ext/" + $mdir
|
||||
mfile = open("Makefile", "w")
|
||||
mfile.printf "\
|
||||
SHELL = /bin/sh
|
||||
|
@ -282,58 +412,66 @@ SHELL = /bin/sh
|
|||
srcdir = #{$srcdir}
|
||||
VPATH = #{$srcdir}
|
||||
|
||||
hdrdir = #{$topdir}
|
||||
topdir = #{$topdir}
|
||||
hdrdir = #{$top_srcdir}
|
||||
DESTDIR =
|
||||
|
||||
CC = @CC@
|
||||
|
||||
prefix = @prefix@
|
||||
CFLAGS = %s -I#{$topdir} -I#{$top_srcdir} -I@includedir@ #{CFLAGS} #$CFLAGS %s
|
||||
DLDFLAGS = #$DLDFLAGS @LDFLAGS@ #$LDFLAGS
|
||||
LDSHARED = @LDSHARED@
|
||||
CFLAGS = %s -I$(topdir) -I$(hdrdir) #{CFLAGS} #$CFLAGS -I@includedir@ %s
|
||||
DLDFLAGS = #$DLDFLAGS #$LDFLAGS
|
||||
LDSHARED = @LDSHARED@ #{defflag}
|
||||
", if $static then "" else "@CCDLFLAGS@" end, $defs.join(" ")
|
||||
|
||||
mfile.printf "\
|
||||
|
||||
program_transform_name = -e @program_transform_name@
|
||||
RUBY_INSTALL_NAME = `t='$(program_transform_name)'; echo ruby | sed $$t`
|
||||
RUBY_INSTALL_NAME = @RUBY_INSTALL_NAME@
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
libdir = @libdir@
|
||||
pkglibdir = $(libdir)/$(RUBY_INSTALL_NAME)
|
||||
#pkglibdir = $(libdir)/$(RUBY_INSTALL_NAME)/@MAJOR@.@MINOR@
|
||||
pkglibdir = $(libdir)/ruby/@MAJOR@.@MINOR@
|
||||
archdir = $(pkglibdir)/@arch@
|
||||
@SET_MAKE@
|
||||
|
||||
#### End of system configuration section. ####
|
||||
|
||||
"
|
||||
mfile.printf "LOCAL_LIBS = %s\n", $local_libs unless $local_libs == ""
|
||||
mfile.printf "LOCAL_LIBS = %s %s\n", $LOCAL_LIBS, $local_flags
|
||||
mfile.printf "LIBS = %s\n", $libs
|
||||
mfile.printf "OBJS = "
|
||||
if !$objs then
|
||||
$objs = []
|
||||
for f in Dir["#{$top_srcdir}/ext/#{$mdir}/*.{c,cc}"]
|
||||
for f in Dir["#{$top_srcdir}/ext/#{$mdir}/*.{#{SRC_EXT.join(%q{,})}}"]
|
||||
f = File.basename(f)
|
||||
f.sub!(/\.(c|cc)$/, ".o")
|
||||
f.sub!(/(#{SRC_EXT.join(%q{|})})$/, $OBJEXT)
|
||||
$objs.push f
|
||||
end
|
||||
end
|
||||
mfile.printf $objs.join(" ")
|
||||
mfile.printf "\n"
|
||||
|
||||
ruby_interpreter = "$(topdir)/miniruby@EXEEXT@"
|
||||
if /mswin32/ =~ RUBY_PLATFORM
|
||||
ruby_interpreter = $topdir + "/miniruby@EXEEXT@"
|
||||
ruby_interpreter.gsub!("/", "\\")
|
||||
end
|
||||
|
||||
mfile.printf <<EOS
|
||||
TARGET = #{target}.#{$static ? "a" : "@DLEXT@"}
|
||||
TARGET = #{target}
|
||||
DLLIB = $(TARGET).#{$static ? $LIBEXT : "@DLEXT@"}
|
||||
|
||||
INSTALL = #{$dots}@INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
RUBY = #{ruby_interpreter} -I$(topdir) -I$(hdrdir)/lib
|
||||
|
||||
binsuffix = @binsuffix@
|
||||
EXEEXT = @EXEEXT@
|
||||
|
||||
all: $(TARGET)
|
||||
all: $(DLLIB)
|
||||
|
||||
clean:; @rm -f *.o *.a *.so *.sl
|
||||
clean:; @rm -f *.#{$OBJEXT} *.so *.sl *.#{$LIBEXT} $(DLLIB)
|
||||
@rm -f *.ilk *.exp *.pdb *.bak
|
||||
@rm -f Makefile extconf.h conftest.*
|
||||
@rm -f core ruby$(binsuffix) *~
|
||||
@rm -f core ruby$(EXEEXT) *~
|
||||
|
||||
realclean: clean
|
||||
EOS
|
||||
|
@ -341,67 +479,65 @@ EOS
|
|||
mfile.printf <<EOS
|
||||
|
||||
install:
|
||||
@test -d $(DESTDIR)$(libdir) || mkdir $(DESTDIR)$(libdir)
|
||||
@test -d $(DESTDIR)$(pkglibdir) || mkdir $(DESTDIR)$(pkglibdir)
|
||||
@test -d $(DESTDIR)$(archdir) || mkdir $(DESTDIR)$(archdir)
|
||||
@$(RUBY) -r ftools -e 'File::makedirs(*ARGV)' $(DESTDIR)$(libdir) $(DESTDIR)$(pkglibdir) $(DESTDIR)$(archdir)
|
||||
EOS
|
||||
if !$static
|
||||
unless $static
|
||||
mfile.printf "\
|
||||
$(INSTALL) $(TARGET) $(DESTDIR)$(archdir)/$(TARGET)
|
||||
@$(RUBY) -r ftools -e 'File::install(ARGV[0], ARGV[1], 0555, true)' $(DLLIB) $(DESTDIR)$(archdir)/$(DLLIB)
|
||||
"
|
||||
end
|
||||
install_rb(mfile)
|
||||
install_rb(mfile, $srcdir)
|
||||
mfile.printf "\n"
|
||||
|
||||
if $static
|
||||
if "@AR@" =~ /^lib\b/i
|
||||
mfile.printf "\
|
||||
$(TARGET): $(OBJS)
|
||||
@AR@ cru $(TARGET) $(OBJS)
|
||||
@-@RANLIB@ $(TARGET) 2> /dev/null || true
|
||||
"
|
||||
elsif "@DLEXT@" != "o"
|
||||
mfile.printf "\
|
||||
$(TARGET): $(OBJS)
|
||||
$(LDSHARED) $(DLDFLAGS) -o $(TARGET) $(OBJS) $(LIBS) $(LOCAL_LIBS)
|
||||
"
|
||||
elsif not File.exist?(target + ".c") and not File.exist?(target + ".cc")
|
||||
if PLATFORM == "m68k-human"
|
||||
mfile.printf "\
|
||||
$(TARGET): $(OBJS)
|
||||
ar cru $(TARGET) $(OBJS)
|
||||
"
|
||||
elsif PLATFORM =~ "-nextstep" || PLATFORM =~ "-openstep" || PLATFORM =~ "-rhapsody"
|
||||
mfile.printf "\
|
||||
$(TARGET): $(OBJS)
|
||||
cc -r $(CFLAGS) -o $(TARGET) $(OBJS)
|
||||
$(DLLIB): $(OBJS)
|
||||
@AR@ /OUT:$(DLLIB) $(OBJS)
|
||||
"
|
||||
else
|
||||
mfile.printf "\
|
||||
$(TARGET): $(OBJS)
|
||||
ld $(DLDFLAGS) -r -o $(TARGET) $(OBJS)
|
||||
$(DLLIB): $(OBJS)
|
||||
@AR@ cru $(DLLIB) $(OBJS)
|
||||
@-@RANLIB@ $(DLLIB) 2> /dev/null || true
|
||||
"
|
||||
end
|
||||
elsif "@DLEXT@" != $OBJEXT
|
||||
mfile.printf "\
|
||||
$(DLLIB): $(OBJS)
|
||||
$(LDSHARED) $(DLDFLAGS) -o $(DLLIB) $(OBJS) $(LIBS) $(LOCAL_LIBS)
|
||||
"
|
||||
elsif RUBY_PLATFORM == "m68k-human"
|
||||
mfile.printf "\
|
||||
$(DLLIB): $(OBJS)
|
||||
ar cru $(DLLIB) $(OBJS)
|
||||
"
|
||||
else
|
||||
mfile.printf "\
|
||||
$(DLLIB): $(OBJS)
|
||||
ld $(DLDFLAGS) -r -o $(DLLIB) $(OBJS)
|
||||
"
|
||||
end
|
||||
|
||||
if File.exist?("depend")
|
||||
dfile = open("depend", "r")
|
||||
if File.exist?("#{$srcdir}/depend")
|
||||
dfile = open("#{$srcdir}/depend", "r")
|
||||
mfile.printf "###\n"
|
||||
while line = dfile.gets()
|
||||
mfile.printf "%s", line
|
||||
mfile.printf "%s", line.gsub('\$\(hdrdir\)/config.h', '$(topdir)/config.h')
|
||||
end
|
||||
dfile.close
|
||||
end
|
||||
mfile.close
|
||||
|
||||
if PLATFORM =~ /beos/
|
||||
if PLATFORM =~ /^powerpc/ then
|
||||
if RUBY_PLATFORM =~ /beos/
|
||||
if RUBY_PLATFORM =~ /^powerpc/ then
|
||||
deffilename = "ruby.exp"
|
||||
else
|
||||
deffilename = "ruby.def"
|
||||
end
|
||||
print "creating ruby.def\n"
|
||||
print "creating #{deffilename}\n"
|
||||
open(deffilename, "w") do |file|
|
||||
file.print("EXPORTS\n") if PLATFORM =~ /^i/
|
||||
file.print("EXPORTS\n") if RUBY_PLATFORM =~ /^i/
|
||||
file.print("Init_#{target}\n")
|
||||
end
|
||||
end
|
||||
|
@ -411,57 +547,95 @@ def extmake(target)
|
|||
if $force_static or $static_ext[target]
|
||||
$static = target
|
||||
else
|
||||
$static = FALSE
|
||||
$static = false
|
||||
end
|
||||
|
||||
return if $nodynamic and not $static
|
||||
unless $install or $clean
|
||||
return if $nodynamic and not $static
|
||||
end
|
||||
|
||||
$OBJEXT = "@OBJEXT@"
|
||||
$LIBEXT = "a"
|
||||
$objs = nil
|
||||
$libs = PLATFORM =~ /cygwin|beos|openstep|nextstep|rhapsody/ ? nil : "-lc"
|
||||
$local_libs = "" # to be assigned in extconf.rb
|
||||
$CFLAGS = ""
|
||||
$LDFLAGS = ""
|
||||
$local_flags = ""
|
||||
case RUBY_PLATFORM
|
||||
when /cygwin|beos|openstep|nextstep|rhapsody/
|
||||
$libs = ""
|
||||
when /mswin32/
|
||||
$LIBEXT = "lib"
|
||||
$libs = ""
|
||||
$local_flags = "$(topdir)/rubymw.lib -link /EXPORT:Init_$(TARGET)"
|
||||
else
|
||||
$libs = "-lc"
|
||||
end
|
||||
$LOCAL_LIBS = "" # to be assigned in extconf.rb
|
||||
dir = with_config("opt-dir")
|
||||
if dir
|
||||
idir = "-I"+dir+"/include"
|
||||
ldir = "-L"+dir+"/lib"
|
||||
end
|
||||
unless idir
|
||||
dir = with_config("opt-include")
|
||||
idir = "-I"+dir if dir
|
||||
end
|
||||
unless ldir
|
||||
dir = with_config("opt-lib")
|
||||
ldir = "-L"+dir if dir
|
||||
end
|
||||
|
||||
$CFLAGS = idir || ""
|
||||
$LDFLAGS = ldir || ""
|
||||
|
||||
begin
|
||||
system "mkdir", target unless File.directory?(target)
|
||||
Dir.chdir target
|
||||
$target = target
|
||||
$mdir = target
|
||||
if $static_ext.size > 0 ||
|
||||
!File.exist?("./Makefile") ||
|
||||
older("./Makefile", "#{$top_srcdir}/ext/@setup@") ||
|
||||
older("./Makefile", "../extmk.rb") ||
|
||||
older("./Makefile", "#{$top_srcdir}/ext/#{target}/extconf.rb")
|
||||
then
|
||||
$defs = []
|
||||
if File.exist?("#{$top_srcdir}/ext/#{target}/extconf.rb")
|
||||
load "#{$top_srcdir}/ext/#{target}/extconf.rb"
|
||||
else
|
||||
create_makefile(target);
|
||||
unless $install or $clean
|
||||
if $static_ext.size > 0 ||
|
||||
!File.exist?("./Makefile") ||
|
||||
older("./Makefile", "#{$top_srcdir}/ext/@setup@") ||
|
||||
older("./Makefile", "../extmk.rb") ||
|
||||
older("./Makefile", "#{$top_srcdir}/ext/#{target}/makefile.rb") ||
|
||||
older("./Makefile", "#{$top_srcdir}/ext/#{target}/extconf.rb")
|
||||
then
|
||||
$defs = []
|
||||
if File.exist?("#{$top_srcdir}/ext/#{target}/makefile.rb")
|
||||
load "#{$top_srcdir}/ext/#{target}/makefile.rb"
|
||||
elsif File.exist?("#{$top_srcdir}/ext/#{target}/extconf.rb")
|
||||
load "#{$top_srcdir}/ext/#{target}/extconf.rb"
|
||||
else
|
||||
create_makefile(target)
|
||||
end
|
||||
end
|
||||
end
|
||||
if File.exist?("./Makefile")
|
||||
if $static
|
||||
$extlist.push [$static,target]
|
||||
$extlist.push [$static,$target]
|
||||
end
|
||||
if $install
|
||||
system "make install DESTDIR=#{$destdir}"
|
||||
system "#{$make} install DESTDIR=#{$destdir}"
|
||||
elsif $clean
|
||||
system "make clean"
|
||||
system "#{$make} clean"
|
||||
else
|
||||
system "make all"
|
||||
system "#{$make} all" or exit
|
||||
end
|
||||
end
|
||||
if $static
|
||||
$extlibs ||= ""
|
||||
$extlibs += " " + $LDFLAGS unless $LDFLAGS == ""
|
||||
$extlibs += " " + $libs if $libs
|
||||
$extlibs += " " + $local_libs unless $local_libs == ""
|
||||
$extlibs += " " + $libs unless $libs == ""
|
||||
$extlibs += " " + $LOCAL_LIBS unless $LOCAL_LIBS == ""
|
||||
end
|
||||
ensure
|
||||
system "rm -f conftest*"
|
||||
Dir.chdir ".."
|
||||
end
|
||||
end
|
||||
|
||||
$make = ENV["MAKE"]
|
||||
$make ||= with_config("make-prog", "make")
|
||||
|
||||
# get static-link modules
|
||||
$static_ext = {}
|
||||
for setup in ["@setup@", "#{$top_srcdir}/ext/@setup@"]
|
||||
|
@ -472,10 +646,12 @@ for setup in ["@setup@", "#{$top_srcdir}/ext/@setup@"]
|
|||
sub!(/#.*$/, '')
|
||||
next if /^\s*$/
|
||||
if /^option +nodynamic/
|
||||
$nodynamic = TRUE
|
||||
$nodynamic = true
|
||||
next
|
||||
end
|
||||
$static_ext[$_.split[0]] = TRUE
|
||||
target = $_.split[0]
|
||||
target = target.downcase if /mswin32/ =~ RUBY_PLATFORM
|
||||
$static_ext[target] = true
|
||||
end
|
||||
f.close
|
||||
break
|
||||
|
@ -493,6 +669,9 @@ for d in Dir["#{$top_srcdir}/ext/*"]
|
|||
print "cleaning ", d, "\n"
|
||||
else
|
||||
print "compiling ", d, "\n"
|
||||
if RUBY_PLATFORM =~ /-aix/ and older("../ruby.imp", "../miniruby")
|
||||
load "#{$top_srcdir}/ext/aix_mksym.rb"
|
||||
end
|
||||
end
|
||||
extmake(d)
|
||||
end
|
||||
|
@ -511,22 +690,29 @@ if $cache_mod
|
|||
f.close
|
||||
end
|
||||
|
||||
exit if $install or $clean
|
||||
if $install or $clean
|
||||
Dir.chdir ".."
|
||||
exit
|
||||
end
|
||||
$extinit = "" unless $extinit
|
||||
|
||||
ruby = "@RUBY_INSTALL_NAME@@EXEEXT@"
|
||||
miniruby = "miniruby@EXEEXT@"
|
||||
|
||||
$extobjs = "" unless $extobjs
|
||||
if $extlist.size > 0
|
||||
for s,t in $extlist
|
||||
f = format("%s/%s.a", s, t)
|
||||
f = format("%s/%s.%s", s, t, $LIBEXT)
|
||||
if File.exist?(f)
|
||||
$extinit += format("\
|
||||
\tInit_%s();\n\
|
||||
\trb_provide(\"%s.o\");\n\
|
||||
\trb_provide(\"%s.so\");\n\
|
||||
", t, t)
|
||||
$extobjs = "" unless $extobjs
|
||||
$extobjs += "ext/"
|
||||
$extobjs += f
|
||||
$extobjs += " "
|
||||
else
|
||||
FALSE
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -537,7 +723,7 @@ if $extlist.size > 0
|
|||
f.printf "}\n"
|
||||
f.close
|
||||
end
|
||||
if older("extinit.o", "extinit.c")
|
||||
if older("extinit.#{$OBJEXT}", "extinit.c")
|
||||
cmd = "@CC@ " + CFLAGS + " -c extinit.c"
|
||||
print cmd, "\n"
|
||||
system cmd or exit 1
|
||||
|
@ -545,24 +731,20 @@ if $extlist.size > 0
|
|||
|
||||
Dir.chdir ".."
|
||||
|
||||
if older("ruby@binsuffix@", "#{$top_srcdir}/ext/@setup@") or older("ruby@binsuffix@", "miniruby@binsuffix@")
|
||||
`rm -f ruby@binsuffix@`
|
||||
if older(ruby, "#{$top_srcdir}/ext/@setup@") or older(ruby, miniruby)
|
||||
system("rm -f #{ruby}")
|
||||
end
|
||||
|
||||
if $extobjs
|
||||
$extobjs = "ext/extinit.o " + $extobjs
|
||||
else
|
||||
$extobjs = "ext/extinit.o "
|
||||
end
|
||||
if PLATFORM =~ /m68k-human|beos/
|
||||
$extobjs = "ext/extinit.#{$OBJEXT} " + $extobjs
|
||||
if RUBY_PLATFORM =~ /m68k-human|beos/
|
||||
$extlibs.gsub!("-L/usr/local/lib", "") if $extlibs
|
||||
end
|
||||
system format('make ruby@binsuffix@ EXTOBJS="%s" EXTLIBS="%s"', $extobjs, $extlibs)
|
||||
system format(%[#{$make} #{ruby} EXTOBJS="%s" EXTLIBS="%s"], $extobjs, $extlibs)
|
||||
else
|
||||
Dir.chdir ".."
|
||||
if older("ruby@binsuffix@", "miniruby@binsuffix@")
|
||||
`rm -f ruby@binsuffix@`
|
||||
system("make ruby@binsuffix@")
|
||||
if older(ruby, miniruby)
|
||||
system("rm -f #{ruby}")
|
||||
system("#{$make} #{ruby}")
|
||||
end
|
||||
end
|
||||
|
||||
|
|
501
ext/extmk.rb.nt
501
ext/extmk.rb.nt
|
@ -1,501 +0,0 @@
|
|||
#! /usr/local/bin/ruby
|
||||
|
||||
$".push 'mkmf.rb' #"
|
||||
|
||||
if ARGV[0] == 'static'
|
||||
$force_static = TRUE
|
||||
ARGV.shift
|
||||
elsif ARGV[0] == 'install'
|
||||
$install = TRUE
|
||||
ARGV.shift
|
||||
elsif ARGV[0] == 'clean'
|
||||
$clean = TRUE
|
||||
ARGV.shift
|
||||
end
|
||||
|
||||
$extlist = []
|
||||
|
||||
$cache_mod = FALSE;
|
||||
$lib_cache = {}
|
||||
$func_cache = {}
|
||||
$hdr_cache = {}
|
||||
|
||||
#$dllopt = '-MD'
|
||||
$dllopt = ''
|
||||
|
||||
if File.exist?("config.cache") then
|
||||
f = open("config.cache", "r")
|
||||
while f.gets
|
||||
case $_
|
||||
when /^lib: ([\w_]+) (yes|no)/
|
||||
$lib_cache[$1] = $2
|
||||
when /^func: ([\w_]+) (yes|no)/
|
||||
$func_cache[$1] = $2
|
||||
when /^hdr: (.+) (yes|no)/
|
||||
$hdr_cache[$1] = $2
|
||||
end
|
||||
end
|
||||
f.close
|
||||
end
|
||||
|
||||
def older(file1, file2)
|
||||
if !File.exist?(file1) then
|
||||
return TRUE
|
||||
end
|
||||
if !File.exist?(file2) then
|
||||
return FALSE
|
||||
end
|
||||
if File.mtime(file1) < File.mtime(file2)
|
||||
return TRUE
|
||||
end
|
||||
return FALSE
|
||||
end
|
||||
|
||||
#LINK = "cl -o conftest.exe -I../.. -Zi -O -I. %s conftest.c %s > nul"
|
||||
LINK = "cl -o conftest.exe -Zi -O %s conftest.c %s > nul"
|
||||
CPP = "cl -E -I../.. -I../../missing -I../../win32 -I. -Zi -O %s conftest.c > nul"
|
||||
|
||||
def try_link(libs)
|
||||
#print(format("try #{LINK}", $CFLAGS, $LDFLAGS, libs))
|
||||
#system(format(LINK, $CFLAGS, $LDFLAGS, libs))
|
||||
print(format("try #{LINK}\n", $CFLAGS, libs))
|
||||
system(format(LINK, $CFLAGS, libs))
|
||||
end
|
||||
|
||||
def try_cpp
|
||||
system(format(CPP, $CFLAGS))
|
||||
end
|
||||
|
||||
def have_library(lib, func)
|
||||
#print format("have_library(%s, %s)\n", lib, func)
|
||||
if $lib_cache[lib]
|
||||
if $lib_cache[lib] == "yes"
|
||||
if $libs#
|
||||
$libs = lib + ".lib " + $libs
|
||||
else
|
||||
$libs = lib + ".lib "
|
||||
end
|
||||
return TRUE
|
||||
else
|
||||
return FALSE
|
||||
end
|
||||
end
|
||||
|
||||
cfile = open("conftest.c", "w")
|
||||
cfile.printf "\
|
||||
#include <windows.h>
|
||||
#include <winsock.h>
|
||||
int main() { return 0; }
|
||||
int t() { %s(); return 0; }
|
||||
", func
|
||||
cfile.close
|
||||
|
||||
begin
|
||||
if $libs
|
||||
libs = lib + ".lib " + $libs
|
||||
else
|
||||
libs = lib + ".lib"
|
||||
end
|
||||
#print "libs=#{libs}\n"
|
||||
unless try_link(libs)
|
||||
#print "fail : #{libs}\n"
|
||||
$lib_cache[lib] = 'no'
|
||||
$cache_mod = TRUE
|
||||
return FALSE
|
||||
end
|
||||
ensure
|
||||
system "rm -f conftest*"
|
||||
end
|
||||
|
||||
$libs = libs
|
||||
$lib_cache[lib] = 'yes'
|
||||
$cache_mod = TRUE
|
||||
return TRUE
|
||||
end
|
||||
|
||||
def have_func(func)
|
||||
if $func_cache[func]
|
||||
if $func_cache[func] == "yes"
|
||||
$defs.push(format("-DHAVE_%s", func.upcase))
|
||||
return TRUE
|
||||
else
|
||||
return FALSE
|
||||
end
|
||||
end
|
||||
|
||||
cfile = open("conftest.c", "w")
|
||||
cfile.printf "\
|
||||
#include <windows.h>
|
||||
#include <winsock.h>
|
||||
//char %s();
|
||||
int main() { return 0; }
|
||||
int t() { %s(); return 0; }
|
||||
", func, func
|
||||
cfile.close
|
||||
|
||||
libs = $libs
|
||||
libs = "" if libs == nil
|
||||
|
||||
begin
|
||||
#print "libs=#{libs}\n"
|
||||
unless try_link(libs)
|
||||
$func_cache[func] = 'no'
|
||||
$cache_mod = TRUE
|
||||
return FALSE
|
||||
end
|
||||
ensure
|
||||
system "rm -f conftest*"
|
||||
end
|
||||
$defs.push(format("-DHAVE_%s", func.upcase))
|
||||
$func_cache[func] = 'yes'
|
||||
$cache_mod = TRUE
|
||||
return TRUE
|
||||
end
|
||||
|
||||
def have_header(header)
|
||||
if $hdr_cache[header]
|
||||
if $hdr_cache[header] == "yes"
|
||||
header.tr!("a-z./\055", "A-Z___")
|
||||
$defs.push(format("-DHAVE_%s", header))
|
||||
return TRUE
|
||||
else
|
||||
return FALSE
|
||||
end
|
||||
end
|
||||
|
||||
cfile = open("conftest.c", "w")
|
||||
cfile.printf "\
|
||||
#include <%s>
|
||||
", header
|
||||
cfile.close
|
||||
|
||||
begin
|
||||
unless try_cpp
|
||||
$hdr_cache[header] = 'no'
|
||||
$cache_mod = TRUE
|
||||
return FALSE
|
||||
end
|
||||
ensure
|
||||
system "rm -f conftest*"
|
||||
end
|
||||
$hdr_cache[header] = 'yes'
|
||||
header.tr!("a-z./\055", "A-Z___")
|
||||
$defs.push(format("-DHAVE_%s", header))
|
||||
$cache_mod = TRUE
|
||||
return TRUE
|
||||
end
|
||||
|
||||
def create_header()
|
||||
if $defs.length > 0
|
||||
hfile = open("extconf.h", "w")
|
||||
for line in $defs
|
||||
line =~ /^-D(.*)/
|
||||
hfile.printf "#define %s 1\n", $1
|
||||
end
|
||||
hfile.close
|
||||
end
|
||||
end
|
||||
|
||||
def create_makefile(target)
|
||||
|
||||
if $libs and "obj" == "obj"
|
||||
libs = $libs.split
|
||||
for lib in libs
|
||||
lib.sub!(/(.*)/, '"\1.lib"') if /.lib$/ !~ lib
|
||||
end
|
||||
$defs.push(format("-DEXTLIB='%s'", libs.join(",")))
|
||||
end
|
||||
$libs = "" unless $libs
|
||||
|
||||
mfile = open("Makefile", "w")
|
||||
mfile.printf "\
|
||||
SHELL = $(COMPSEC)
|
||||
|
||||
#### Start of system configuration section. ####
|
||||
|
||||
srcdir = .
|
||||
VPATH = .
|
||||
|
||||
CC = cl
|
||||
|
||||
CFLAGS = %s -I../.. -I../../missing -I../../win32 -I. -O -DNT %s #$CFLAGS %s
|
||||
|
||||
RUBYLIB = ../../ruby.lib
|
||||
DLDFLAGS = /DLL
|
||||
LDSHARED =
|
||||
", if $static then "" else "-fpic" end, $dllopt, $defs.join(" ")
|
||||
|
||||
if $force_static
|
||||
print "static\n"
|
||||
else
|
||||
print "non static\n"
|
||||
end
|
||||
|
||||
mfile.printf "\
|
||||
|
||||
libdir = /usr/local/lib/ruby/i386-mswin32
|
||||
|
||||
|
||||
#### End of system configuration section. ####
|
||||
"
|
||||
mfile.printf "LOCAL_LIBS = %s\n", $local_libs if $local_libs
|
||||
mfile.printf "LIBS = %s\n", $libs
|
||||
mfile.printf "OBJS = "
|
||||
if !$objs then
|
||||
$objs = Dir["*.c"]
|
||||
for f in $objs
|
||||
f.sub!(/\.c$/, ".obj")
|
||||
end
|
||||
end
|
||||
mfile.printf $objs.join(" ")
|
||||
mfile.printf "\n"
|
||||
|
||||
dots = if "ginstall -c" =~ /^\// then "" else "../" end
|
||||
mfile.printf "\
|
||||
TARGET = %s.%s
|
||||
|
||||
INSTALL = %sginstall -c
|
||||
|
||||
DEFFILE = %s.def
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
clean:; @rm -f *.obj *.lib *.exp vc*.pdb *.bak *.def
|
||||
@rm -f Makefile extconf.h conftest.*
|
||||
|
||||
realclean: clean
|
||||
", target,
|
||||
if $force_static then "lib" else "dll" end, dots, target
|
||||
|
||||
if !$static
|
||||
mfile.printf "\
|
||||
|
||||
install: $(libdir)/$(TARGET)
|
||||
|
||||
$(libdir)/$(TARGET): $(TARGET)
|
||||
@test -d $(libdir) || mkdir $(libdir)
|
||||
$(INSTALL) $(TARGET) $(libdir)/$(TARGET)
|
||||
"
|
||||
else
|
||||
mfile.printf "\
|
||||
|
||||
install:;
|
||||
"
|
||||
end
|
||||
|
||||
if $force_static
|
||||
mfile.printf "\
|
||||
$(TARGET): $(OBJS)
|
||||
lib /OUT:$(TARGET) $(OBJS)
|
||||
"
|
||||
else
|
||||
mfile.printf "\
|
||||
$(DEFFILE):
|
||||
echo $(DEFFILE)
|
||||
|
||||
$(TARGET): $(OBJS) $(DEFFILE)
|
||||
cl -DLL -o$(TARGET) $(OBJS) $(RUBYLIB) -link /DEF:$(DEFFILE)
|
||||
"
|
||||
end
|
||||
|
||||
if File.exist?("depend")
|
||||
dfile = open("depend", "r")
|
||||
mfile.printf "###\n"
|
||||
while line = dfile.gets()
|
||||
mfile.printf "%s", line
|
||||
end
|
||||
dfile.close
|
||||
end
|
||||
mfile.close
|
||||
if $static
|
||||
#printf format("push %s,%s\n", $static, target); ##debug print##
|
||||
$extlist.push [$static,target]
|
||||
end
|
||||
end
|
||||
|
||||
#template of .def file.
|
||||
def create_def(basename)
|
||||
defname = sprintf("%s.def", basename)
|
||||
f = open(defname, "w")
|
||||
f.printf "\
|
||||
LIBRARY %s.dll
|
||||
CODE LOADONCALL
|
||||
DATA LOADONCALL
|
||||
DESCRIPTION 'win32 %s.dll'
|
||||
EXPORTS
|
||||
|
||||
Init_%s
|
||||
", basename, basename, basename
|
||||
f.close
|
||||
|
||||
end
|
||||
|
||||
def extmake(target)
|
||||
if $force_static or $static_ext[target]
|
||||
$static = target
|
||||
else
|
||||
$static = FALSE
|
||||
end
|
||||
|
||||
return if $nodynamic and not $static
|
||||
|
||||
$local_libs = nil
|
||||
$libs = nil
|
||||
$objs = nil
|
||||
$CFLAGS = nil
|
||||
$LDFLAGS = nil
|
||||
|
||||
begin
|
||||
Dir.chdir target
|
||||
if $static_ext.size > 0 ||
|
||||
!File.exist?("./Makefile") ||
|
||||
older("./Makefile", "../Setup") ||
|
||||
older("./Makefile", "../extmk.rb") ||
|
||||
older("./Makefile", "./extconf.rb")
|
||||
then
|
||||
$defs = []
|
||||
if File.exist?("extconf.rb")
|
||||
load "extconf.rb"
|
||||
else
|
||||
create_makefile(target);
|
||||
end
|
||||
end
|
||||
|
||||
if !File.exist?("#{target}.def")
|
||||
create_def(target)
|
||||
end
|
||||
|
||||
if File.exist?("./Makefile")
|
||||
if $install
|
||||
system "nmake install"
|
||||
if File.directory? "./lib"
|
||||
for i in Dir["./lib/*.rb"]
|
||||
system "ginstall -c #{i} /usr/local/lib/ruby/i386-mswin32"
|
||||
end
|
||||
end
|
||||
elsif $clean
|
||||
system "nmake clean"
|
||||
else
|
||||
#print "!!!make!!!\n"
|
||||
system "nmake all"
|
||||
end
|
||||
end
|
||||
if $static
|
||||
$extlibs = " "
|
||||
$extlibs += " " + $LDFLAGS if $LDFLAGS
|
||||
$extlibs += " " + $local_libs if $local_libs
|
||||
$extlibs += " " + $libs if $libs
|
||||
end
|
||||
ensure
|
||||
Dir.chdir ".."
|
||||
end
|
||||
end
|
||||
|
||||
# get static-link modules
|
||||
$static_ext = {}
|
||||
if File.file? "./Setup"
|
||||
f = open("./Setup")
|
||||
while f.gets()
|
||||
$_.chop!
|
||||
sub!(/#.*$/, '')
|
||||
next if /^\s*$/
|
||||
#print $_, "\n"
|
||||
|
||||
if /^option +nodynamic/
|
||||
$nodynamic = TRUE
|
||||
next
|
||||
end
|
||||
$static_ext[$_.split[0]] = TRUE
|
||||
end
|
||||
f.close
|
||||
end
|
||||
|
||||
for d in Dir["*"]
|
||||
File.directory?(d) || next
|
||||
File.file?(d + "/MANIFEST") || next
|
||||
|
||||
d = $1 if d =~ /\/([\/]*)$/
|
||||
if $install
|
||||
print "installing ", d, "\n"
|
||||
elsif $clean
|
||||
print "cleaning ", d, "\n"
|
||||
else
|
||||
print "compiling ", d, "\n"
|
||||
end
|
||||
extmake(d)
|
||||
end
|
||||
|
||||
if $cache_mod
|
||||
f = open("config.cache", "w")
|
||||
for k,v in $lib_cache
|
||||
f.printf "lib: %s %s\n", k, v
|
||||
end
|
||||
for k,v in $func_cache
|
||||
f.printf "func: %s %s\n", k, v
|
||||
end
|
||||
for k,v in $hdr_cache
|
||||
f.printf "hdr: %s %s\n", k, v
|
||||
end
|
||||
f.close
|
||||
end
|
||||
|
||||
exit if $install or $clean
|
||||
$extinit = " " unless $extinit
|
||||
$extobjs = ""
|
||||
if $extlist.size > 0
|
||||
for s,t in $extlist
|
||||
#for s,t in $static_ext
|
||||
#f = format("%s/%s.obj", s, t)
|
||||
#f = format("%s/%s.obj", s, s)
|
||||
l = format("%s/%s.lib", s, s)
|
||||
if File.exist?(l)
|
||||
$extinit += format("\
|
||||
\tInit_%s();\n\
|
||||
\trb_provide(\"%s.o\");\n\
|
||||
", s, s)
|
||||
$extobjs += "ext/"
|
||||
#$extobjs += f # *.obj
|
||||
$extobjs += l # *.lib
|
||||
$extobjs += " "
|
||||
else
|
||||
FALSE
|
||||
end
|
||||
end
|
||||
|
||||
if older("extinit.c", "Setup")
|
||||
f = open("extinit.c", "w")
|
||||
f.printf "void Init_ext() {\n"
|
||||
f.printf $extinit
|
||||
f.printf "}\n"
|
||||
f.close
|
||||
end
|
||||
if older("extinit.obj", "extinit.c")
|
||||
cmd = "cl -Zi -O -I. -c extinit.c"
|
||||
print cmd, "\n"
|
||||
system cmd or exit 1
|
||||
end
|
||||
|
||||
Dir.chdir ".."
|
||||
|
||||
if older("ruby.exe", "ext/Setup") or older("ruby.exe", "miniruby.exe")
|
||||
`rm -f ruby.exe`
|
||||
end
|
||||
|
||||
$extobjs = "ext/extinit.obj " + $extobjs
|
||||
#$extlibs = ""
|
||||
#print "EXTLIBS=#{$extlibs}\n"
|
||||
$extlibs.gsub!("-L/usr/local/lib", "") if $extlibs
|
||||
$extlibs.gsub!(" +", " ") if $extlibs
|
||||
#print "EXTLIBS=#{$extlibs}\n"
|
||||
|
||||
system format('nmake ruby.exe EXTOBJS="%s" EXTLIBS="%s"', $extobjs, $extlibs)
|
||||
else
|
||||
Dir.chdir ".."
|
||||
if older("ruby.exe", "miniruby.exe")
|
||||
`rm -f ruby.exe`
|
||||
`cp miniruby.exe ruby.exe`
|
||||
end
|
||||
end
|
||||
#Local variables:
|
||||
# mode: ruby
|
||||
#end:
|
|
@ -1 +1 @@
|
|||
fcntl.o: fcntl.c $(hdrdir)/ruby.h $(hdrdir)/config.h $(hdrdir)/defines.h
|
||||
fcntl.o: fcntl.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
|
||||
|
|
|
@ -34,6 +34,7 @@ pack up your own arguments to pass as args for locking functions, etc.
|
|||
#include "ruby.h"
|
||||
#include <fcntl.h>
|
||||
|
||||
void
|
||||
Init_fcntl()
|
||||
{
|
||||
VALUE mFcntl = rb_define_module("Fcntl");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
MANIFEST
|
||||
README
|
||||
depend
|
||||
extconf.rb
|
||||
marshal.c
|
||||
marshal.doc
|
||||
gdbm.c
|
|
@ -0,0 +1 @@
|
|||
gdbm ext-library for Ruby 1.3 or later
|
|
@ -0,0 +1 @@
|
|||
gdbm.o: gdbm.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
|
|
@ -0,0 +1,7 @@
|
|||
require 'mkmf'
|
||||
|
||||
dir_config("gdbm")
|
||||
if have_library("gdbm", "gdbm_open") and
|
||||
have_header("gdbm.h")
|
||||
create_makefile("gdbm")
|
||||
end
|
|
@ -0,0 +1,604 @@
|
|||
/************************************************
|
||||
|
||||
gdbm.c -
|
||||
|
||||
$Author$
|
||||
$Date$
|
||||
modified at: Mon Jan 24 15:59:52 JST 1994
|
||||
|
||||
************************************************/
|
||||
|
||||
#include "ruby.h"
|
||||
|
||||
#include <gdbm.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#ifdef USE_CWGUSI
|
||||
# include <sys/errno.h>
|
||||
#endif
|
||||
|
||||
VALUE cGDBM;
|
||||
|
||||
#define MY_BLOCK_SIZE (2048)
|
||||
#define MY_FATAL_FUNC (0)
|
||||
|
||||
struct dbmdata {
|
||||
int di_size;
|
||||
GDBM_FILE di_dbm;
|
||||
};
|
||||
|
||||
static void
|
||||
closed_dbm()
|
||||
{
|
||||
rb_raise(rb_eRuntimeError, "closed GDBM file");
|
||||
}
|
||||
|
||||
#define GetDBM(obj, dbmp) {\
|
||||
Data_Get_Struct(obj, struct dbmdata, dbmp);\
|
||||
if (dbmp->di_dbm == 0) closed_dbm();\
|
||||
}
|
||||
|
||||
static void
|
||||
free_dbm(dbmp)
|
||||
struct dbmdata *dbmp;
|
||||
{
|
||||
if (dbmp->di_dbm) gdbm_close(dbmp->di_dbm);
|
||||
free(dbmp);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fgdbm_s_open(argc, argv, klass)
|
||||
int argc;
|
||||
VALUE *argv;
|
||||
VALUE klass;
|
||||
{
|
||||
VALUE file, vmode;
|
||||
GDBM_FILE dbm;
|
||||
struct dbmdata *dbmp;
|
||||
int mode;
|
||||
VALUE obj;
|
||||
|
||||
if (rb_scan_args(argc, argv, "11", &file, &vmode) == 1) {
|
||||
mode = 0666; /* default value */
|
||||
}
|
||||
else if (NIL_P(vmode)) {
|
||||
mode = -1; /* return nil if DB not exist */
|
||||
}
|
||||
else {
|
||||
mode = NUM2INT(vmode);
|
||||
}
|
||||
Check_SafeStr(file);
|
||||
|
||||
dbm = 0;
|
||||
if (mode >= 0)
|
||||
dbm = gdbm_open(RSTRING(file)->ptr, MY_BLOCK_SIZE,
|
||||
O_RDWR|O_CREAT, mode, MY_FATAL_FUNC);
|
||||
if (!dbm)
|
||||
dbm = gdbm_open(RSTRING(file)->ptr, MY_BLOCK_SIZE,
|
||||
O_RDWR, mode, MY_FATAL_FUNC);
|
||||
if (!dbm)
|
||||
dbm = gdbm_open(RSTRING(file)->ptr, MY_BLOCK_SIZE,
|
||||
O_RDONLY, mode, MY_FATAL_FUNC);
|
||||
|
||||
if (!dbm) {
|
||||
if (mode == -1) return Qnil;
|
||||
rb_sys_fail(RSTRING(file)->ptr);
|
||||
}
|
||||
|
||||
obj = Data_Make_Struct(klass,struct dbmdata,0,free_dbm,dbmp);
|
||||
dbmp->di_dbm = dbm;
|
||||
dbmp->di_size = -1;
|
||||
rb_obj_call_init(obj, argc, argv);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fgdbm_close(obj)
|
||||
VALUE obj;
|
||||
{
|
||||
struct dbmdata *dbmp;
|
||||
|
||||
Data_Get_Struct(obj, struct dbmdata, dbmp);
|
||||
if (dbmp->di_dbm == 0) closed_dbm();
|
||||
gdbm_close(dbmp->di_dbm);
|
||||
dbmp->di_dbm = 0;
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fgdbm_fetch(obj, keystr)
|
||||
VALUE obj, keystr;
|
||||
{
|
||||
datum key, value;
|
||||
struct dbmdata *dbmp;
|
||||
GDBM_FILE dbm;
|
||||
|
||||
Check_Type(keystr, T_STRING);
|
||||
key.dptr = RSTRING(keystr)->ptr;
|
||||
key.dsize = RSTRING(keystr)->len;
|
||||
|
||||
GetDBM(obj, dbmp);
|
||||
dbm = dbmp->di_dbm;
|
||||
value = gdbm_fetch(dbm, key);
|
||||
if (value.dptr == 0) {
|
||||
return Qnil;
|
||||
}
|
||||
return rb_tainted_str_new(value.dptr, value.dsize);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fgdbm_indexes(argc, argv, obj)
|
||||
int argc;
|
||||
VALUE *argv;
|
||||
VALUE obj;
|
||||
{
|
||||
VALUE new;
|
||||
int i;
|
||||
|
||||
new = rb_ary_new2(argc);
|
||||
for (i=0; i<argc; i++) {
|
||||
rb_ary_push(new, fgdbm_fetch(obj, argv[i]));
|
||||
}
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fgdbm_delete(obj, keystr)
|
||||
VALUE obj, keystr;
|
||||
{
|
||||
datum key, value;
|
||||
struct dbmdata *dbmp;
|
||||
GDBM_FILE dbm;
|
||||
|
||||
rb_secure(4);
|
||||
Check_Type(keystr, T_STRING);
|
||||
key.dptr = RSTRING(keystr)->ptr;
|
||||
key.dsize = RSTRING(keystr)->len;
|
||||
|
||||
GetDBM(obj, dbmp);
|
||||
dbm = dbmp->di_dbm;
|
||||
|
||||
value = gdbm_fetch(dbm, key);
|
||||
if (value.dptr == 0) {
|
||||
if (rb_iterator_p()) rb_yield(keystr);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
if (gdbm_delete(dbm, key)) {
|
||||
dbmp->di_size = -1;
|
||||
rb_raise(rb_eRuntimeError, "dbm_delete failed");
|
||||
}
|
||||
else if (dbmp->di_size >= 0) {
|
||||
dbmp->di_size--;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fgdbm_shift(obj)
|
||||
VALUE obj;
|
||||
{
|
||||
datum key, val;
|
||||
struct dbmdata *dbmp;
|
||||
GDBM_FILE dbm;
|
||||
VALUE keystr, valstr;
|
||||
|
||||
rb_secure(4);
|
||||
GetDBM(obj, dbmp);
|
||||
dbm = dbmp->di_dbm;
|
||||
|
||||
key = gdbm_firstkey(dbm);
|
||||
if (!key.dptr) return Qnil;
|
||||
val = gdbm_fetch(dbm, key);
|
||||
gdbm_delete(dbm, key);
|
||||
|
||||
keystr = rb_tainted_str_new(key.dptr, key.dsize);
|
||||
valstr = rb_tainted_str_new(val.dptr, val.dsize);
|
||||
return rb_assoc_new(keystr, valstr);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fgdbm_delete_if(obj)
|
||||
VALUE obj;
|
||||
{
|
||||
datum key, val;
|
||||
struct dbmdata *dbmp;
|
||||
GDBM_FILE dbm;
|
||||
VALUE keystr, valstr;
|
||||
|
||||
rb_secure(4);
|
||||
GetDBM(obj, dbmp);
|
||||
dbm = dbmp->di_dbm;
|
||||
for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) {
|
||||
val = gdbm_fetch(dbm, key);
|
||||
keystr = rb_tainted_str_new(key.dptr, key.dsize);
|
||||
valstr = rb_tainted_str_new(val.dptr, val.dsize);
|
||||
if (RTEST(rb_yield(rb_assoc_new(keystr, valstr)))) {
|
||||
if (gdbm_delete(dbm, key)) {
|
||||
rb_raise(rb_eRuntimeError, "dbm_delete failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fgdbm_clear(obj)
|
||||
VALUE obj;
|
||||
{
|
||||
datum key, nextkey;
|
||||
struct dbmdata *dbmp;
|
||||
GDBM_FILE dbm;
|
||||
|
||||
rb_secure(4);
|
||||
GetDBM(obj, dbmp);
|
||||
dbm = dbmp->di_dbm;
|
||||
dbmp->di_size = -1;
|
||||
for (key = gdbm_firstkey(dbm); key.dptr; key = nextkey) {
|
||||
nextkey = gdbm_nextkey(dbm, key);
|
||||
if (gdbm_delete(dbm, key)) {
|
||||
rb_raise(rb_eRuntimeError, "dbm_delete failed");
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fgdbm_invert(obj)
|
||||
VALUE obj;
|
||||
{
|
||||
datum key, val;
|
||||
struct dbmdata *dbmp;
|
||||
GDBM_FILE dbm;
|
||||
VALUE keystr, valstr;
|
||||
VALUE hash = rb_hash_new();
|
||||
|
||||
GetDBM(obj, dbmp);
|
||||
dbm = dbmp->di_dbm;
|
||||
for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) {
|
||||
val = gdbm_fetch(dbm, key);
|
||||
keystr = rb_tainted_str_new(key.dptr, key.dsize);
|
||||
valstr = rb_tainted_str_new(val.dptr, val.dsize);
|
||||
rb_hash_aset(hash, valstr, keystr);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
each_pair(obj)
|
||||
VALUE obj;
|
||||
{
|
||||
return rb_funcall(obj, rb_intern("each_pair"), 0, 0);
|
||||
}
|
||||
|
||||
static VALUE fgdbm_store _((VALUE,VALUE,VALUE));
|
||||
|
||||
static VALUE
|
||||
update_i(pair, dbm)
|
||||
VALUE pair, dbm;
|
||||
{
|
||||
Check_Type(pair, T_ARRAY);
|
||||
if (RARRAY(pair)->len < 2) {
|
||||
rb_raise(rb_eArgError, "pair must be [key, value]");
|
||||
}
|
||||
fgdbm_store(dbm, RARRAY(pair)->ptr[0], RARRAY(pair)->ptr[1]);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fgdbm_update(obj, other)
|
||||
VALUE obj, other;
|
||||
{
|
||||
rb_iterate(each_pair, other, update_i, obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fgdbm_replace(obj, other)
|
||||
VALUE obj, other;
|
||||
{
|
||||
fgdbm_clear(obj);
|
||||
rb_iterate(each_pair, other, update_i, obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fgdbm_store(obj, keystr, valstr)
|
||||
VALUE obj, keystr, valstr;
|
||||
{
|
||||
datum key, val;
|
||||
struct dbmdata *dbmp;
|
||||
GDBM_FILE dbm;
|
||||
|
||||
if (valstr == Qnil) {
|
||||
fgdbm_delete(obj, keystr);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
rb_secure(4);
|
||||
keystr = rb_obj_as_string(keystr);
|
||||
|
||||
key.dptr = RSTRING(keystr)->ptr;
|
||||
key.dsize = RSTRING(keystr)->len;
|
||||
|
||||
if (NIL_P(valstr)) return fgdbm_delete(obj, keystr);
|
||||
|
||||
valstr = rb_obj_as_string(valstr);
|
||||
val.dptr = RSTRING(valstr)->ptr;
|
||||
val.dsize = RSTRING(valstr)->len;
|
||||
|
||||
Data_Get_Struct(obj, struct dbmdata, dbmp);
|
||||
dbmp->di_size = -1;
|
||||
dbm = dbmp->di_dbm;
|
||||
if (gdbm_store(dbm, key, val, GDBM_REPLACE)) {
|
||||
#ifdef HAVE_DBM_CLAERERR
|
||||
gdbm_clearerr(dbm);
|
||||
#endif
|
||||
if (errno == EPERM) rb_sys_fail(0);
|
||||
rb_raise(rb_eRuntimeError, "dbm_store failed");
|
||||
}
|
||||
|
||||
return valstr;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fgdbm_length(obj)
|
||||
VALUE obj;
|
||||
{
|
||||
datum key;
|
||||
struct dbmdata *dbmp;
|
||||
GDBM_FILE dbm;
|
||||
int i = 0;
|
||||
|
||||
Data_Get_Struct(obj, struct dbmdata, dbmp);
|
||||
if (dbmp->di_size > 0) return INT2FIX(dbmp->di_size);
|
||||
dbm = dbmp->di_dbm;
|
||||
|
||||
for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) {
|
||||
i++;
|
||||
}
|
||||
dbmp->di_size = i;
|
||||
|
||||
return INT2FIX(i);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fgdbm_empty_p(obj)
|
||||
VALUE obj;
|
||||
{
|
||||
datum key;
|
||||
struct dbmdata *dbmp;
|
||||
GDBM_FILE dbm;
|
||||
int i = 0;
|
||||
|
||||
Data_Get_Struct(obj, struct dbmdata, dbmp);
|
||||
if (dbmp->di_size < 0) {
|
||||
dbm = dbmp->di_dbm;
|
||||
|
||||
for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
i = dbmp->di_size;
|
||||
}
|
||||
if (i == 0) return Qtrue;
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fgdbm_each_value(obj)
|
||||
VALUE obj;
|
||||
{
|
||||
datum key, val;
|
||||
struct dbmdata *dbmp;
|
||||
GDBM_FILE dbm;
|
||||
|
||||
GetDBM(obj, dbmp);
|
||||
dbm = dbmp->di_dbm;
|
||||
for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) {
|
||||
val = gdbm_fetch(dbm, key);
|
||||
rb_yield(rb_tainted_str_new(val.dptr, val.dsize));
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fgdbm_each_key(obj)
|
||||
VALUE obj;
|
||||
{
|
||||
datum key;
|
||||
struct dbmdata *dbmp;
|
||||
GDBM_FILE dbm;
|
||||
|
||||
GetDBM(obj, dbmp);
|
||||
dbm = dbmp->di_dbm;
|
||||
for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) {
|
||||
rb_yield(rb_tainted_str_new(key.dptr, key.dsize));
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fgdbm_each_pair(obj)
|
||||
VALUE obj;
|
||||
{
|
||||
datum key, val;
|
||||
GDBM_FILE dbm;
|
||||
struct dbmdata *dbmp;
|
||||
VALUE keystr, valstr;
|
||||
|
||||
GetDBM(obj, dbmp);
|
||||
dbm = dbmp->di_dbm;
|
||||
|
||||
for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) {
|
||||
val = gdbm_fetch(dbm, key);
|
||||
keystr = rb_tainted_str_new(key.dptr, key.dsize);
|
||||
valstr = rb_tainted_str_new(val.dptr, val.dsize);
|
||||
rb_yield(rb_assoc_new(keystr, valstr));
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fgdbm_keys(obj)
|
||||
VALUE obj;
|
||||
{
|
||||
datum key;
|
||||
struct dbmdata *dbmp;
|
||||
GDBM_FILE dbm;
|
||||
VALUE ary;
|
||||
|
||||
GetDBM(obj, dbmp);
|
||||
dbm = dbmp->di_dbm;
|
||||
|
||||
ary = rb_ary_new();
|
||||
for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) {
|
||||
rb_ary_push(ary, rb_tainted_str_new(key.dptr, key.dsize));
|
||||
}
|
||||
|
||||
return ary;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fgdbm_values(obj)
|
||||
VALUE obj;
|
||||
{
|
||||
datum key, val;
|
||||
struct dbmdata *dbmp;
|
||||
GDBM_FILE dbm;
|
||||
VALUE ary;
|
||||
|
||||
GetDBM(obj, dbmp);
|
||||
dbm = dbmp->di_dbm;
|
||||
|
||||
ary = rb_ary_new();
|
||||
for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) {
|
||||
val = gdbm_fetch(dbm, key);
|
||||
rb_ary_push(ary, rb_tainted_str_new(val.dptr, val.dsize));
|
||||
}
|
||||
|
||||
return ary;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fgdbm_has_key(obj, keystr)
|
||||
VALUE obj, keystr;
|
||||
{
|
||||
datum key, val;
|
||||
struct dbmdata *dbmp;
|
||||
GDBM_FILE dbm;
|
||||
|
||||
Check_Type(keystr, T_STRING);
|
||||
key.dptr = RSTRING(keystr)->ptr;
|
||||
key.dsize = RSTRING(keystr)->len;
|
||||
|
||||
GetDBM(obj, dbmp);
|
||||
dbm = dbmp->di_dbm;
|
||||
val = gdbm_fetch(dbm, key);
|
||||
if (val.dptr) return Qtrue;
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fgdbm_has_value(obj, valstr)
|
||||
VALUE obj, valstr;
|
||||
{
|
||||
datum key, val;
|
||||
struct dbmdata *dbmp;
|
||||
GDBM_FILE dbm;
|
||||
|
||||
Check_Type(valstr, T_STRING);
|
||||
val.dptr = RSTRING(valstr)->ptr;
|
||||
val.dsize = RSTRING(valstr)->len;
|
||||
|
||||
GetDBM(obj, dbmp);
|
||||
dbm = dbmp->di_dbm;
|
||||
for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) {
|
||||
val = gdbm_fetch(dbm, key);
|
||||
if (val.dsize == RSTRING(valstr)->len &&
|
||||
memcmp(val.dptr, RSTRING(valstr)->ptr, val.dsize) == 0)
|
||||
return Qtrue;
|
||||
}
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fgdbm_to_a(obj)
|
||||
VALUE obj;
|
||||
{
|
||||
datum key, val;
|
||||
struct dbmdata *dbmp;
|
||||
GDBM_FILE dbm;
|
||||
VALUE ary;
|
||||
|
||||
GetDBM(obj, dbmp);
|
||||
dbm = dbmp->di_dbm;
|
||||
|
||||
ary = rb_ary_new();
|
||||
for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) {
|
||||
val = gdbm_fetch(dbm, key);
|
||||
rb_ary_push(ary, rb_assoc_new(rb_tainted_str_new(key.dptr, key.dsize),
|
||||
rb_tainted_str_new(val.dptr, val.dsize)));
|
||||
}
|
||||
|
||||
return ary;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fgdbm_reorganize(obj)
|
||||
VALUE obj;
|
||||
{
|
||||
struct dbmdata *dbmp;
|
||||
GDBM_FILE dbm;
|
||||
|
||||
rb_secure(4);
|
||||
GetDBM(obj, dbmp);
|
||||
dbm = dbmp->di_dbm;
|
||||
gdbm_reorganize(dbm);
|
||||
return obj;
|
||||
}
|
||||
|
||||
void
|
||||
Init_gdbm()
|
||||
{
|
||||
cGDBM = rb_define_class("GDBM", rb_cObject);
|
||||
rb_include_module(cGDBM, rb_mEnumerable);
|
||||
|
||||
rb_define_singleton_method(cGDBM, "open", fgdbm_s_open, -1);
|
||||
rb_define_singleton_method(cGDBM, "new", fgdbm_s_open, -1);
|
||||
rb_define_method(cGDBM, "close", fgdbm_close, 0);
|
||||
rb_define_method(cGDBM, "[]", fgdbm_fetch, 1);
|
||||
rb_define_method(cGDBM, "[]=", fgdbm_store, 2);
|
||||
rb_define_method(cGDBM, "indexes", fgdbm_indexes, -1);
|
||||
rb_define_method(cGDBM, "indices", fgdbm_indexes, -1);
|
||||
rb_define_method(cGDBM, "length", fgdbm_length, 0);
|
||||
rb_define_alias(cGDBM, "size", "length");
|
||||
rb_define_method(cGDBM, "empty?", fgdbm_empty_p, 0);
|
||||
rb_define_method(cGDBM, "each", fgdbm_each_pair, 0);
|
||||
rb_define_method(cGDBM, "each_value", fgdbm_each_value, 0);
|
||||
rb_define_method(cGDBM, "each_key", fgdbm_each_key, 0);
|
||||
rb_define_method(cGDBM, "each_pair", fgdbm_each_pair, 0);
|
||||
rb_define_method(cGDBM, "keys", fgdbm_keys, 0);
|
||||
rb_define_method(cGDBM, "values", fgdbm_values, 0);
|
||||
rb_define_method(cGDBM, "shift", fgdbm_shift, 1);
|
||||
rb_define_method(cGDBM, "delete", fgdbm_delete, 1);
|
||||
rb_define_method(cGDBM, "delete_if", fgdbm_delete_if, 0);
|
||||
rb_define_method(cGDBM, "clear", fgdbm_clear, 0);
|
||||
rb_define_method(cGDBM,"invert", fgdbm_invert, 0);
|
||||
rb_define_method(cGDBM,"update", fgdbm_update, 1);
|
||||
rb_define_method(cGDBM,"replace", fgdbm_replace, 1);
|
||||
rb_define_method(cGDBM,"reorganize", fgdbm_reorganize, 0);
|
||||
|
||||
rb_define_method(cGDBM, "include?", fgdbm_has_key, 1);
|
||||
rb_define_method(cGDBM, "has_key?", fgdbm_has_key, 1);
|
||||
rb_define_method(cGDBM, "has_value?", fgdbm_has_value, 1);
|
||||
rb_define_method(cGDBM, "key?", fgdbm_has_key, 1);
|
||||
rb_define_method(cGDBM, "value?", fgdbm_has_value, 1);
|
||||
|
||||
rb_define_method(cGDBM, "to_a", fgdbm_to_a, 0);
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
MANIFEST
|
||||
extconf.rb
|
||||
gtk.c
|
||||
test.rb
|
||||
test.xpm
|
||||
test0.rb
|
||||
test1.rb
|
||||
test2.rb
|
||||
test3.rb
|
||||
test4.rb
|
||||
test5.rb
|
||||
test6.rb
|
||||
test7.rb
|
||||
test8.rb
|
||||
test9.rb
|
||||
testa.rb
|
||||
testb.rb
|
||||
testc.rb
|
|
@ -1,6 +0,0 @@
|
|||
require "mkmf"
|
||||
if have_library("glib", "g_print") and
|
||||
have_library("gdk", "gdk_init") and
|
||||
have_library("gtk", "gtk_init")
|
||||
create_makefile("gtk")
|
||||
end
|
5904
ext/gtk/gtk.c
5904
ext/gtk/gtk.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,96 +0,0 @@
|
|||
require 'gtk'
|
||||
|
||||
def create_menu(depth)
|
||||
return nil if depth < 1
|
||||
|
||||
menu = Gtk::Menu::new()
|
||||
group = nil
|
||||
submenu = nil
|
||||
|
||||
for i in 0..4
|
||||
buf = sprintf("item %2d - %d", depth, i+1)
|
||||
# menuitem = Gtk::MenuItem::new(buf)
|
||||
menuitem = Gtk::RadioMenuItem.new(group, buf)
|
||||
group = menuitem.group
|
||||
if depth % 2
|
||||
menuitem.set_show_toggle TRUE
|
||||
end
|
||||
menu.append menuitem
|
||||
menuitem.show
|
||||
if depth > 0
|
||||
unless submenu
|
||||
submenu = create_menu(depth - 1)
|
||||
end
|
||||
menuitem.set_submenu submenu
|
||||
end
|
||||
end
|
||||
return menu
|
||||
end
|
||||
|
||||
window = Gtk::Window::new(Gtk::WINDOW_TOPLEVEL)
|
||||
window.signal_connect("destroy") do
|
||||
exit
|
||||
end
|
||||
window.signal_connect("delete_event") do
|
||||
exit
|
||||
end
|
||||
window.set_title("menus")
|
||||
window.border_width(0)
|
||||
|
||||
box1 = Gtk::VBox::new(FALSE, 0)
|
||||
window.add box1
|
||||
box1.show
|
||||
|
||||
menubar = Gtk::MenuBar::new()
|
||||
box1.pack_start menubar, FALSE, TRUE, 0
|
||||
menubar.show
|
||||
|
||||
menu = create_menu(2)
|
||||
menuitem = Gtk::MenuItem::new("test\nline2")
|
||||
menuitem.set_submenu menu
|
||||
menubar.append menuitem
|
||||
menuitem.show
|
||||
|
||||
menuitem = Gtk::MenuItem::new("foo")
|
||||
menuitem.set_submenu menu
|
||||
menubar.append menuitem
|
||||
menuitem.show
|
||||
|
||||
menuitem = Gtk::MenuItem::new("bar")
|
||||
menuitem.set_submenu menu
|
||||
menubar.append menuitem
|
||||
menuitem.show
|
||||
|
||||
box2 = Gtk::VBox::new(FALSE, 10)
|
||||
box2.border_width 10
|
||||
box1.pack_start box2, TRUE, TRUE, 0
|
||||
box2.show
|
||||
|
||||
optionmenu = Gtk::OptionMenu::new()
|
||||
optionmenu.set_menu create_menu(1)
|
||||
optionmenu.set_history 4
|
||||
box2.pack_start optionmenu, TRUE, TRUE, 0
|
||||
optionmenu.show
|
||||
|
||||
separator = Gtk::HSeparator::new()
|
||||
box1.pack_start(separator, FALSE, TRUE, 0)
|
||||
separator.show
|
||||
|
||||
box2 = Gtk::HBox::new(FALSE, 10)
|
||||
box2.border_width(10)
|
||||
box1.pack_start(box2, FALSE, TRUE, 0)
|
||||
box2.show
|
||||
|
||||
button = Gtk::Button::new("close")
|
||||
button.signal_connect("clicked") do
|
||||
window.destroy
|
||||
exit
|
||||
end
|
||||
box2.pack_start(button, TRUE, TRUE, 0)
|
||||
button.set_flags(Gtk::CAN_DEFAULT);
|
||||
button.grab_default
|
||||
button.show
|
||||
|
||||
window.show
|
||||
|
||||
Gtk::main()
|
|
@ -1,92 +0,0 @@
|
|||
/* XPM */
|
||||
static char *openfile[] = {
|
||||
/* width height num_colors chars_per_pixel */
|
||||
" 20 19 66 2",
|
||||
/* colors */
|
||||
".. c None",
|
||||
".# c #000000",
|
||||
".a c #dfdfdf",
|
||||
".b c #7f7f7f",
|
||||
".c c #006f6f",
|
||||
".d c #00efef",
|
||||
".e c #009f9f",
|
||||
".f c #004040",
|
||||
".g c #00bfbf",
|
||||
".h c #ff0000",
|
||||
".i c #ffffff",
|
||||
".j c #7f0000",
|
||||
".k c #007070",
|
||||
".l c #00ffff",
|
||||
".m c #00a0a0",
|
||||
".n c #004f4f",
|
||||
".o c #00cfcf",
|
||||
".p c #8f8f8f",
|
||||
".q c #6f6f6f",
|
||||
".r c #a0a0a0",
|
||||
".s c #7f7f00",
|
||||
".t c #007f7f",
|
||||
".u c #5f5f5f",
|
||||
".v c #707070",
|
||||
".w c #00f0f0",
|
||||
".x c #009090",
|
||||
".y c #ffff00",
|
||||
".z c #0000ff",
|
||||
".A c #00afaf",
|
||||
".B c #00d0d0",
|
||||
".C c #00dfdf",
|
||||
".D c #005f5f",
|
||||
".E c #00b0b0",
|
||||
".F c #001010",
|
||||
".G c #00c0c0",
|
||||
".H c #000f0f",
|
||||
".I c #00007f",
|
||||
".J c #005050",
|
||||
".K c #002f2f",
|
||||
".L c #dfcfcf",
|
||||
".M c #dfd0d0",
|
||||
".N c #006060",
|
||||
".O c #00e0e0",
|
||||
".P c #00ff00",
|
||||
".Q c #002020",
|
||||
".R c #dfc0c0",
|
||||
".S c #008080",
|
||||
".T c #001f1f",
|
||||
".U c #003f3f",
|
||||
".V c #007f00",
|
||||
".W c #00000f",
|
||||
".X c #000010",
|
||||
".Y c #00001f",
|
||||
".Z c #000020",
|
||||
".0 c #00002f",
|
||||
".1 c #000030",
|
||||
".2 c #00003f",
|
||||
".3 c #000040",
|
||||
".4 c #00004f",
|
||||
".5 c #000050",
|
||||
".6 c #00005f",
|
||||
".7 c #000060",
|
||||
".8 c #00006f",
|
||||
".9 c #000070",
|
||||
"#. c #7f7f80",
|
||||
"## c #9f9f9f",
|
||||
/* pixels */
|
||||
"........................................",
|
||||
"........................................",
|
||||
"........................................",
|
||||
".......................#.#.#............",
|
||||
".....................#.......#...#......",
|
||||
"...............................#.#......",
|
||||
".......#.#.#.................#.#.#......",
|
||||
".....#.y.i.y.#.#.#.#.#.#.#..............",
|
||||
".....#.i.y.i.y.i.y.i.y.i.#..............",
|
||||
".....#.y.i.y.i.y.i.y.i.y.#..............",
|
||||
".....#.i.y.i.y.#.#.#.#.#.#.#.#.#.#.#....",
|
||||
".....#.y.i.y.#.s.s.s.s.s.s.s.s.s.#......",
|
||||
".....#.i.y.#.s.s.s.s.s.s.s.s.s.#........",
|
||||
".....#.y.#.s.s.s.s.s.s.s.s.s.#..........",
|
||||
".....#.#.s.s.s.s.s.s.s.s.s.#............",
|
||||
".....#.#.#.#.#.#.#.#.#.#.#..............",
|
||||
"........................................",
|
||||
"........................................",
|
||||
"........................................"
|
||||
};
|
|
@ -1,13 +0,0 @@
|
|||
require 'gtk'
|
||||
|
||||
window = Gtk::Window::new(Gtk::WINDOW_TOPLEVEL)
|
||||
window.border_width(10)
|
||||
button = Gtk::Button::new("Hello World")
|
||||
button.signal_connect("clicked") do
|
||||
print "hello world\n"
|
||||
exit
|
||||
end
|
||||
window.add(button)
|
||||
button.show
|
||||
window.show
|
||||
Gtk::main()
|
|
@ -1,41 +0,0 @@
|
|||
require 'gtk'
|
||||
|
||||
window = Gtk::Window::new(Gtk::WINDOW_TOPLEVEL)
|
||||
window.set_title("entry")
|
||||
window.border_width(0)
|
||||
|
||||
box1 = Gtk::VBox::new(FALSE, 0)
|
||||
window.add(box1)
|
||||
box1.show
|
||||
|
||||
box2 = Gtk::VBox::new(FALSE, 10)
|
||||
box2.border_width(10)
|
||||
box1.pack_start(box2, TRUE, TRUE, 0)
|
||||
box2.show
|
||||
|
||||
entry = Gtk::Entry::new()
|
||||
entry.set_text("hello world")
|
||||
box2.pack_start(entry, TRUE, TRUE, 0)
|
||||
entry.show
|
||||
|
||||
separator = Gtk::HSeparator::new()
|
||||
box1.pack_start(separator, FALSE, TRUE, 0)
|
||||
separator.show
|
||||
|
||||
box2 = Gtk::VBox::new(FALSE, 10)
|
||||
box2.border_width(10)
|
||||
box1.pack_start(box2, FALSE, TRUE, 0)
|
||||
box2.show
|
||||
|
||||
button = Gtk::Button::new("close")
|
||||
button.signal_connect("clicked") do
|
||||
window.destroy
|
||||
exit
|
||||
end
|
||||
box2.pack_start(button, TRUE, TRUE, 0)
|
||||
button.set_flags(Gtk::CAN_DEFAULT);
|
||||
button.grab_default
|
||||
button.show
|
||||
window.show
|
||||
|
||||
Gtk::main()
|
|
@ -1,89 +0,0 @@
|
|||
require 'gtk'
|
||||
|
||||
window = Gtk::Window::new(Gtk::WINDOW_TOPLEVEL)
|
||||
window.set_title("list")
|
||||
window.border_width(0)
|
||||
|
||||
box1 = Gtk::VBox::new(FALSE, 0)
|
||||
window.add(box1)
|
||||
box1.show
|
||||
|
||||
box2 = Gtk::VBox::new(FALSE, 10)
|
||||
box2.border_width(10)
|
||||
box1.pack_start(box2, TRUE, TRUE, 0)
|
||||
box2.show
|
||||
|
||||
scrolled_win = Gtk::ScrolledWindow::new()
|
||||
scrolled_win.set_policy(Gtk::POLICY_AUTOMATIC,Gtk::POLICY_AUTOMATIC)
|
||||
box2.pack_start(scrolled_win, TRUE, TRUE, 0)
|
||||
scrolled_win.show
|
||||
|
||||
list = Gtk::List::new()
|
||||
list.set_selection_mode(Gtk::SELECTION_MULTIPLE)
|
||||
list.set_selection_mode(Gtk::SELECTION_BROWSE)
|
||||
scrolled_win.add(list)
|
||||
list.show
|
||||
|
||||
for i in [
|
||||
"hello",
|
||||
"world",
|
||||
"blah",
|
||||
"foo",
|
||||
"bar",
|
||||
"argh",
|
||||
"spencer",
|
||||
"is a",
|
||||
"wussy",
|
||||
"programmer",
|
||||
]
|
||||
list_item = Gtk::ListItem::new(i)
|
||||
list.add(list_item)
|
||||
list_item.show
|
||||
end
|
||||
|
||||
button = Gtk::Button::new("add")
|
||||
button.set_flags(Gtk::CAN_FOCUS);
|
||||
i = 1
|
||||
button.signal_connect("clicked") do
|
||||
list_item = Gtk::ListItem::new(format("added item %d", i))
|
||||
list.add(list_item)
|
||||
list_item.show
|
||||
i += 1
|
||||
end
|
||||
box2.pack_start(button, FALSE, TRUE, 0)
|
||||
button.show
|
||||
|
||||
button = Gtk::Button::new("remove")
|
||||
button.set_flags(Gtk::CAN_FOCUS);
|
||||
button.signal_connect("clicked") do
|
||||
tmp_list = list.selection
|
||||
list.remove_items(tmp_list)
|
||||
for i in tmp_list
|
||||
i.destroy
|
||||
end
|
||||
end
|
||||
box2.pack_start(button, FALSE, TRUE, 0)
|
||||
button.show
|
||||
|
||||
separator = Gtk::HSeparator::new()
|
||||
box1.pack_start(separator, FALSE, TRUE, 0)
|
||||
separator.show
|
||||
|
||||
box2 = Gtk::VBox::new(FALSE, 10)
|
||||
box2.border_width(10)
|
||||
box1.pack_start(box2, FALSE, TRUE, 0)
|
||||
box2.show
|
||||
|
||||
button = Gtk::Button::new("close")
|
||||
button.signal_connect("clicked") do
|
||||
window.destroy
|
||||
exit
|
||||
end
|
||||
box2.pack_start(button, TRUE, TRUE, 0)
|
||||
button.set_flags(Gtk::CAN_DEFAULT);
|
||||
button.grab_default
|
||||
button.show
|
||||
|
||||
window.show
|
||||
|
||||
Gtk::main()
|
|
@ -1,16 +0,0 @@
|
|||
require 'gtk'
|
||||
|
||||
window = Gtk::FileSelection::new("file selection dialog")
|
||||
window.position(Gtk::WIN_POS_MOUSE)
|
||||
window.border_width(0)
|
||||
|
||||
window.ok_button.signal_connect("clicked") do
|
||||
print window.get_filename, "\n"
|
||||
end
|
||||
window.cancel_button.signal_connect("clicked") do
|
||||
window.destroy
|
||||
exit
|
||||
end
|
||||
window.show
|
||||
|
||||
Gtk::main()
|
|
@ -1,77 +0,0 @@
|
|||
require 'gtk'
|
||||
|
||||
window = Gtk::Window::new(Gtk::WINDOW_TOPLEVEL)
|
||||
window.set_title("notebook")
|
||||
window.border_width(0)
|
||||
|
||||
box1 = Gtk::VBox::new(FALSE, 0)
|
||||
window.add(box1)
|
||||
box1.show
|
||||
|
||||
box2 = Gtk::VBox::new(FALSE, 10)
|
||||
box2.border_width(10)
|
||||
box1.pack_start(box2, TRUE, TRUE, 0)
|
||||
box2.show
|
||||
|
||||
notebook = Gtk::Notebook::new()
|
||||
notebook.set_tab_pos(Gtk::POS_TOP)
|
||||
box2.pack_start(notebook, TRUE, TRUE, 0)
|
||||
notebook.show
|
||||
|
||||
for i in 1..5
|
||||
frame = Gtk::Frame::new(format("Page %d", i))
|
||||
frame.border_width(10)
|
||||
frame.set_usize(200, 150)
|
||||
frame.show
|
||||
|
||||
label = Gtk::Label::new(format("Box %d", i))
|
||||
frame.add label
|
||||
label.show
|
||||
|
||||
label = Gtk::Label::new(format("Tab %d", i))
|
||||
notebook.append_page frame, label
|
||||
end
|
||||
|
||||
separator = Gtk::HSeparator::new()
|
||||
box1.pack_start(separator, FALSE, TRUE, 0)
|
||||
separator.show
|
||||
|
||||
box2 = Gtk::HBox::new(FALSE, 10)
|
||||
box2.border_width(10)
|
||||
box1.pack_start(box2, FALSE, TRUE, 0)
|
||||
box2.show
|
||||
|
||||
button = Gtk::Button::new("close")
|
||||
button.signal_connect("clicked") do
|
||||
window.destroy
|
||||
exit
|
||||
end
|
||||
box2.pack_start(button, TRUE, TRUE, 0)
|
||||
button.set_flags(Gtk::CAN_DEFAULT);
|
||||
button.grab_default
|
||||
button.show
|
||||
|
||||
button = Gtk::Button::new("next")
|
||||
button.signal_connect("clicked") do
|
||||
notebook.next_page
|
||||
end
|
||||
box2.pack_start(button, TRUE, TRUE, 0)
|
||||
button.show
|
||||
|
||||
button = Gtk::Button::new("prev")
|
||||
button.signal_connect("clicked") do
|
||||
notebook.prev_page
|
||||
end
|
||||
box2.pack_start(button, TRUE, TRUE, 0)
|
||||
button.show
|
||||
|
||||
button = Gtk::Button::new("rotate")
|
||||
button.signal_connect("clicked") do
|
||||
notebook.set_tab_pos((notebook.tab_pos+1)%4)
|
||||
end
|
||||
box2.pack_start(button, TRUE, TRUE, 0)
|
||||
button.show
|
||||
|
||||
window.show
|
||||
|
||||
Gtk::main()
|
|
@ -1,63 +0,0 @@
|
|||
require 'gtk'
|
||||
|
||||
window = Gtk::Window::new(Gtk::WINDOW_TOPLEVEL)
|
||||
window.set_title("buttons")
|
||||
window.border_width(0)
|
||||
|
||||
box1 = Gtk::VBox::new(FALSE, 0)
|
||||
window.add(box1)
|
||||
box1.show
|
||||
|
||||
table = Gtk::Table::new(3, 3, FALSE)
|
||||
table.set_row_spacings(5)
|
||||
table.set_col_spacings(5)
|
||||
table.border_width(10)
|
||||
box1.pack_start(table, TRUE, TRUE, 0)
|
||||
table.show
|
||||
|
||||
button = []
|
||||
0.upto(8) do |i|
|
||||
button.push Gtk::Button::new("button"+(i+1))
|
||||
end
|
||||
0.upto(8) do |i|
|
||||
button[i].signal_connect("clicked") do |w|
|
||||
if button[i+1].visible?
|
||||
button[i+1].hide
|
||||
else
|
||||
button[i+1].show
|
||||
end
|
||||
end
|
||||
button[i].show
|
||||
end
|
||||
table.attach(button[0], 0, 1, 0, 1, nil, nil, 0, 0)
|
||||
table.attach(button[1], 1, 2, 1, 2, nil, nil, 0, 0)
|
||||
table.attach(button[2], 2, 3, 2, 3, nil, nil, 0, 0)
|
||||
table.attach(button[3], 0, 1, 2, 3, nil, nil, 0, 0)
|
||||
table.attach(button[4], 2, 3, 0, 1, nil, nil, 0, 0)
|
||||
table.attach(button[5], 1, 2, 2, 3, nil, nil, 0, 0)
|
||||
table.attach(button[6], 1, 2, 0, 1, nil, nil, 0, 0)
|
||||
table.attach(button[7], 2, 3, 1, 2, nil, nil, 0, 0)
|
||||
table.attach(button[8], 0, 1, 1, 2, nil, nil, 0, 0)
|
||||
|
||||
separator = Gtk::HSeparator::new()
|
||||
box1.pack_start(separator, FALSE, TRUE, 0)
|
||||
separator.show
|
||||
|
||||
box2 = Gtk::VBox::new(FALSE, 10)
|
||||
box2.border_width(10)
|
||||
box1.pack_start(box2, FALSE, TRUE, 0)
|
||||
box2.show
|
||||
|
||||
close = Gtk::Button::new("close")
|
||||
close.signal_connect("clicked") do
|
||||
window.destroy
|
||||
exit
|
||||
end
|
||||
box2.pack_start(close, TRUE, TRUE, 0)
|
||||
close.set_flags(Gtk::CAN_DEFAULT);
|
||||
close.grab_default
|
||||
close.show
|
||||
|
||||
window.show
|
||||
|
||||
Gtk::main()
|
|
@ -1,49 +0,0 @@
|
|||
require 'gtk'
|
||||
|
||||
window = Gtk::Window::new(Gtk::WINDOW_TOPLEVEL)
|
||||
window.set_title("toggle buttons")
|
||||
window.border_width(0)
|
||||
|
||||
box1 = Gtk::VBox::new(FALSE, 0)
|
||||
window.add(box1)
|
||||
box1.show
|
||||
|
||||
box2 = Gtk::VBox::new(FALSE, 10)
|
||||
box2.border_width(10)
|
||||
box1.pack_start(box2, TRUE, TRUE, 0)
|
||||
box2.show
|
||||
|
||||
button = Gtk::ToggleButton::new("button1")
|
||||
box2.pack_start(button, TRUE, TRUE, 0)
|
||||
button.show
|
||||
|
||||
button = Gtk::ToggleButton::new("button2")
|
||||
box2.pack_start(button, TRUE, TRUE, 0)
|
||||
button.show
|
||||
|
||||
button = Gtk::ToggleButton::new("button3")
|
||||
box2.pack_start(button, TRUE, TRUE, 0)
|
||||
button.show
|
||||
|
||||
separator = Gtk::HSeparator::new()
|
||||
box1.pack_start(separator, FALSE, TRUE, 0)
|
||||
separator.show
|
||||
|
||||
box2 = Gtk::VBox::new(FALSE, 10)
|
||||
box2.border_width(10)
|
||||
box1.pack_start(box2, FALSE, TRUE, 0)
|
||||
box2.show
|
||||
|
||||
close = Gtk::Button::new("close")
|
||||
close.signal_connect("clicked") do
|
||||
window.destroy
|
||||
exit
|
||||
end
|
||||
box2.pack_start(close, TRUE, TRUE, 0)
|
||||
close.set_flags(Gtk::CAN_DEFAULT);
|
||||
close.grab_default
|
||||
close.show
|
||||
|
||||
window.show
|
||||
|
||||
Gtk::main()
|
|
@ -1,49 +0,0 @@
|
|||
require 'gtk'
|
||||
|
||||
window = Gtk::Window::new(Gtk::WINDOW_TOPLEVEL)
|
||||
window.set_title("check buttons")
|
||||
window.border_width(0)
|
||||
|
||||
box1 = Gtk::VBox::new(FALSE, 0)
|
||||
window.add(box1)
|
||||
box1.show
|
||||
|
||||
box2 = Gtk::VBox::new(FALSE, 10)
|
||||
box2.border_width(10)
|
||||
box1.pack_start(box2, TRUE, TRUE, 0)
|
||||
box2.show
|
||||
|
||||
button = Gtk::CheckButton::new("button1")
|
||||
box2.pack_start(button, TRUE, TRUE, 0)
|
||||
button.show
|
||||
|
||||
button = Gtk::CheckButton::new("button2")
|
||||
box2.pack_start(button, TRUE, TRUE, 0)
|
||||
button.show
|
||||
|
||||
button = Gtk::CheckButton::new("button3")
|
||||
box2.pack_start(button, TRUE, TRUE, 0)
|
||||
button.show
|
||||
|
||||
separator = Gtk::HSeparator::new()
|
||||
box1.pack_start(separator, FALSE, TRUE, 0)
|
||||
separator.show
|
||||
|
||||
box2 = Gtk::VBox::new(FALSE, 10)
|
||||
box2.border_width(10)
|
||||
box1.pack_start(box2, FALSE, TRUE, 0)
|
||||
box2.show
|
||||
|
||||
close = Gtk::Button::new("close")
|
||||
close.signal_connect("clicked") do
|
||||
window.destroy
|
||||
exit
|
||||
end
|
||||
box2.pack_start(close, TRUE, TRUE, 0)
|
||||
close.set_flags(Gtk::CAN_DEFAULT);
|
||||
close.grab_default
|
||||
close.show
|
||||
|
||||
window.show
|
||||
|
||||
Gtk::main()
|
|
@ -1,49 +0,0 @@
|
|||
require 'gtk'
|
||||
|
||||
window = Gtk::Window::new(Gtk::WINDOW_TOPLEVEL)
|
||||
window.set_title("radio buttons")
|
||||
window.border_width(0)
|
||||
|
||||
box1 = Gtk::VBox::new(FALSE, 0)
|
||||
window.add(box1)
|
||||
box1.show
|
||||
|
||||
box2 = Gtk::VBox::new(FALSE, 10)
|
||||
box2.border_width 10
|
||||
box1.pack_start(box2, TRUE, TRUE, 0)
|
||||
box2.show
|
||||
|
||||
button = Gtk::RadioButton::new("button1")
|
||||
box2.pack_start(button, TRUE, TRUE, 0)
|
||||
button.show
|
||||
|
||||
button = Gtk::RadioButton::new(button, "button2")
|
||||
box2.pack_start(button, TRUE, TRUE, 0)
|
||||
button.show
|
||||
|
||||
button = Gtk::RadioButton::new(button, "button3")
|
||||
box2.pack_start(button, TRUE, TRUE, 0)
|
||||
button.show
|
||||
|
||||
separator = Gtk::HSeparator::new()
|
||||
box1.pack_start(separator, FALSE, TRUE, 0)
|
||||
separator.show
|
||||
|
||||
box2 = Gtk::VBox::new(FALSE, 10)
|
||||
box2.border_width(10)
|
||||
box1.pack_start(box2, FALSE, TRUE, 0)
|
||||
box2.show
|
||||
|
||||
close = Gtk::Button::new("close")
|
||||
close.signal_connect("clicked") do
|
||||
window.destroy
|
||||
exit
|
||||
end
|
||||
box2.pack_start(close, TRUE, TRUE, 0)
|
||||
close.set_flags(Gtk::CAN_DEFAULT);
|
||||
close.grab_default
|
||||
close.show
|
||||
|
||||
window.show
|
||||
|
||||
Gtk::main()
|
|
@ -1,98 +0,0 @@
|
|||
require 'gtk'
|
||||
|
||||
def create_bbox_window(horizontal, title, pos, spacing, cw, ch, layout)
|
||||
window = Gtk::Window::new(Gtk::WINDOW_TOPLEVEL)
|
||||
window.set_title(title)
|
||||
window.signal_connect("destroy") do
|
||||
window.destroy
|
||||
end
|
||||
window.signal_connect("delete_event") do
|
||||
window.hide
|
||||
window.destroy
|
||||
end
|
||||
if horizontal
|
||||
window.set_usize(550, 60)
|
||||
window.set_uposition(150, pos)
|
||||
else
|
||||
window.set_usize(150, 400)
|
||||
window.set_uposition(pos, 200)
|
||||
end
|
||||
box1 = Gtk::VBox::new(FALSE, 0)
|
||||
window.add box1
|
||||
box1.show
|
||||
if horizontal
|
||||
bbox = Gtk::HButtonBox::new()
|
||||
else
|
||||
bbox = Gtk::VButtonBox::new()
|
||||
end
|
||||
bbox.set_layout layout
|
||||
bbox.set_spacing spacing
|
||||
bbox.set_child_size cw, ch
|
||||
bbox.show
|
||||
box1.border_width 25
|
||||
box1.pack_start(bbox, TRUE, TRUE, 0)
|
||||
button = Gtk::Button::new("OK")
|
||||
bbox.add button
|
||||
button.signal_connect("clicked") do
|
||||
window.hide
|
||||
window.destroy
|
||||
end
|
||||
button.show
|
||||
|
||||
button = Gtk::Button::new("Cancel")
|
||||
bbox.add button
|
||||
button.signal_connect("clicked") do
|
||||
window.hide
|
||||
window.destroy
|
||||
end
|
||||
button.show
|
||||
|
||||
button = Gtk::Button::new("Help")
|
||||
bbox.add button
|
||||
button.show
|
||||
|
||||
window.show
|
||||
end
|
||||
|
||||
def test_hbbox
|
||||
create_bbox_window(TRUE, "Spread", 50, 40, 85, 25, Gtk::BUTTONBOX_SPREAD);
|
||||
create_bbox_window(TRUE, "Edge", 250, 40, 85, 28, Gtk::BUTTONBOX_EDGE);
|
||||
create_bbox_window(TRUE, "Start", 450, 40, 85, 25, Gtk::BUTTONBOX_START);
|
||||
create_bbox_window(TRUE, "End", 650, 15, 30, 25, Gtk::BUTTONBOX_END);
|
||||
end
|
||||
|
||||
def test_vbbox
|
||||
create_bbox_window(FALSE, "Spread", 50, 40, 85, 25, Gtk::BUTTONBOX_SPREAD);
|
||||
create_bbox_window(FALSE, "Edge", 250, 40, 85, 28, Gtk::BUTTONBOX_EDGE);
|
||||
create_bbox_window(FALSE, "Start", 450, 40, 85, 25, Gtk::BUTTONBOX_START);
|
||||
create_bbox_window(FALSE, "End", 650, 15, 30, 25, Gtk::BUTTONBOX_END);
|
||||
end
|
||||
|
||||
window = Gtk::Window::new(Gtk::WINDOW_TOPLEVEL)
|
||||
window.signal_connect("delete_event") do
|
||||
window.destroy
|
||||
exit
|
||||
end
|
||||
window.set_title("button box")
|
||||
window.border_width(20)
|
||||
|
||||
bbox = Gtk::HButtonBox::new()
|
||||
window.add(bbox)
|
||||
bbox.show
|
||||
|
||||
button = Gtk::Button::new("Horizontal")
|
||||
def button.clicked(*args)
|
||||
test_hbbox
|
||||
end
|
||||
bbox.add button
|
||||
button.show
|
||||
|
||||
button = Gtk::Button::new("Vertical")
|
||||
def button.clicked(*args)
|
||||
test_vbbox
|
||||
end
|
||||
bbox.add button
|
||||
button.show
|
||||
window.show
|
||||
|
||||
Gtk::main()
|
|
@ -1,78 +0,0 @@
|
|||
require 'gtk'
|
||||
|
||||
window = Gtk::Window::new(Gtk::WINDOW_TOPLEVEL)
|
||||
window.set_title("toolbar test")
|
||||
window.set_policy(TRUE, TRUE, TRUE)
|
||||
window.signal_connect("destroy") do
|
||||
exit
|
||||
end
|
||||
window.signal_connect("delete_event") do
|
||||
exit
|
||||
end
|
||||
window.border_width(0)
|
||||
window.realize
|
||||
|
||||
toolbar = Gtk::Toolbar::new(Gtk::ORIENTATION_HORIZONTAL, Gtk::TOOLBAR_BOTH)
|
||||
toolbar.append_item "Horizontal", "Horizontal toolbar layout",
|
||||
Gtk::Pixmap::new(*Gdk::Pixmap::create_from_xpm(window.window,
|
||||
nil,
|
||||
#window.style.bg[Gtk::STATE_NORMAL],
|
||||
"test.xpm")), nil do
|
||||
toolbar.set_orientation Gtk::ORIENTATION_HORIZONTAL
|
||||
end
|
||||
toolbar.append_item "Vertival", "Vertical toolbar layout",
|
||||
Gtk::Pixmap::new(*Gdk::Pixmap::create_from_xpm(window.window,
|
||||
nil, #window.style.bg[Gtk::STATE_NORMAL],
|
||||
"test.xpm")), nil do
|
||||
toolbar.set_orientation Gtk::ORIENTATION_VERTICAL
|
||||
end
|
||||
toolbar.append_space
|
||||
toolbar.append_item "Icons", "Only show toolbar icons",
|
||||
Gtk::Pixmap::new(*Gdk::Pixmap::create_from_xpm(window.window,
|
||||
nil, #window.style.bg[Gtk::STATE_NORMAL],
|
||||
"test.xpm")), nil do
|
||||
toolbar.set_style Gtk::TOOLBAR_ICONS
|
||||
end
|
||||
toolbar.append_item "Text", "Only show toolbar text",
|
||||
Gtk::Pixmap::new(*Gdk::Pixmap::create_from_xpm(window.window,
|
||||
nil,#window.style.bg[Gtk::STATE_NORMAL],
|
||||
"test.xpm")), nil do
|
||||
toolbar.set_style Gtk::TOOLBAR_TEXT
|
||||
end
|
||||
toolbar.append_item "Both", "Show toolbar icons and text",
|
||||
Gtk::Pixmap::new(*Gdk::Pixmap::create_from_xpm(window.window,
|
||||
nil, #window.style.bg[Gtk::STATE_NORMAL],
|
||||
"test.xpm")), nil do
|
||||
toolbar.set_style Gtk::TOOLBAR_BOTH
|
||||
end
|
||||
toolbar.append_space
|
||||
toolbar.append_item "Small", "User small spaces",
|
||||
Gtk::Pixmap::new(*Gdk::Pixmap::create_from_xpm(window.window,
|
||||
nil,#window.style.bg[Gtk::STATE_NORMAL],
|
||||
"test.xpm")), nil do
|
||||
toolbar.set_space_size 5
|
||||
end
|
||||
toolbar.append_item "Big", "User big spaces",
|
||||
Gtk::Pixmap::new(*Gdk::Pixmap::create_from_xpm(window.window,
|
||||
nil,#window.style.bg[Gtk::STATE_NORMAL],
|
||||
"test.xpm")), nil do
|
||||
toolbar.set_space_size 10
|
||||
end
|
||||
toolbar.append_space
|
||||
toolbar.append_item "Enable", "Enable tooltips",
|
||||
Gtk::Pixmap::new(*Gdk::Pixmap::create_from_xpm(window.window,
|
||||
nil,#window.style.bg[Gtk::STATE_NORMAL],
|
||||
"test.xpm")), nil do
|
||||
toolbar.set_tooltips TRUE
|
||||
end
|
||||
toolbar.append_item "Disable", "Disable tooltips",
|
||||
Gtk::Pixmap::new(*Gdk::Pixmap::create_from_xpm(window.window,
|
||||
nil,#window.style.bg[Gtk::STATE_NORMAL],
|
||||
"test.xpm")), nil do
|
||||
toolbar.set_tooltips FALSE
|
||||
end
|
||||
window.add toolbar
|
||||
toolbar.show
|
||||
window.show
|
||||
|
||||
Gtk::main()
|
|
@ -1,78 +0,0 @@
|
|||
require 'gtk'
|
||||
|
||||
window = Gtk::Window::new(Gtk::WINDOW_TOPLEVEL)
|
||||
window.signal_connect("destroy") do
|
||||
exit
|
||||
end
|
||||
window.signal_connect("delete_event") do
|
||||
exit
|
||||
end
|
||||
window.set_title("buttons")
|
||||
window.border_width(0)
|
||||
|
||||
box1 = Gtk::VBox::new(FALSE, 0)
|
||||
window.add box1
|
||||
box1.show
|
||||
|
||||
box2 = Gtk::HBox::new(FALSE, 5)
|
||||
box2.border_width 10
|
||||
box1.pack_start box2, TRUE, TRUE, 0
|
||||
box2.show
|
||||
|
||||
label = Gtk::Label::new("Hello World")
|
||||
frame = Gtk::Frame::new("Frame 1")
|
||||
box2.pack_start frame, TRUE, TRUE, 0
|
||||
frame.show
|
||||
|
||||
box3 = Gtk::VBox::new(FALSE, 5)
|
||||
box3.border_width 5
|
||||
frame.add box3
|
||||
box3.show
|
||||
|
||||
button = Gtk::Button::new("switch")
|
||||
button.signal_connect("clicked") do
|
||||
label.reparent box3
|
||||
end
|
||||
box3.pack_start button, FALSE, TRUE, 0
|
||||
button.show
|
||||
box3.pack_start label, FALSE, TRUE, 0
|
||||
label.show
|
||||
|
||||
frame = Gtk::Frame::new("Frame 2")
|
||||
box2.pack_start frame, TRUE, TRUE, 0
|
||||
frame.show
|
||||
|
||||
box4 = Gtk::VBox::new(FALSE, 5)
|
||||
box4.border_width 5
|
||||
frame.add box4
|
||||
box4.show
|
||||
|
||||
button = Gtk::Button::new("switch")
|
||||
button.signal_connect("clicked") do
|
||||
label.reparent box4
|
||||
end
|
||||
box4.pack_start button, FALSE, TRUE, 0
|
||||
button.show
|
||||
|
||||
separator = Gtk::HSeparator::new()
|
||||
box1.pack_start(separator, FALSE, TRUE, 0)
|
||||
separator.show
|
||||
|
||||
box2 = Gtk::HBox::new(FALSE, 10)
|
||||
box2.border_width(10)
|
||||
box1.pack_start(box2, FALSE, TRUE, 0)
|
||||
box2.show
|
||||
|
||||
button = Gtk::Button::new("close")
|
||||
button.signal_connect("clicked") do
|
||||
window.destroy
|
||||
exit
|
||||
end
|
||||
box2.pack_start(button, TRUE, TRUE, 0)
|
||||
button.set_flags(Gtk::CAN_DEFAULT);
|
||||
button.grab_default
|
||||
button.show
|
||||
|
||||
window.show
|
||||
|
||||
Gtk::main()
|
|
@ -1,64 +0,0 @@
|
|||
require 'gtk'
|
||||
|
||||
window = Gtk::Window::new(Gtk::WINDOW_TOPLEVEL)
|
||||
window.signal_connect("destroy") do
|
||||
exit
|
||||
end
|
||||
window.signal_connect("delete_event") do
|
||||
exit
|
||||
end
|
||||
window.set_title("pixmap")
|
||||
window.border_width(0)
|
||||
window.realize
|
||||
|
||||
box1 = Gtk::VBox::new(FALSE, 0)
|
||||
window.add box1
|
||||
box1.show
|
||||
|
||||
box2 = Gtk::HBox::new(FALSE, 10)
|
||||
box2.border_width 10
|
||||
box1.pack_start box2, TRUE, TRUE, 0
|
||||
box2.show
|
||||
|
||||
button = Gtk::Button::new()
|
||||
box2.pack_start button, FALSE, FALSE, 0
|
||||
button.show
|
||||
|
||||
style = button.style
|
||||
pixmap, mask = Gdk::Pixmap::create_from_xpm(window.window,
|
||||
nil,
|
||||
#style.bg[Gtk::STATE_NORMAL],
|
||||
"test.xpm")
|
||||
pixmapwid = Gtk::Pixmap::new(pixmap, mask)
|
||||
label = Gtk::Label::new("Pixmap\ntest")
|
||||
box3 = Gtk::HBox::new(FALSE, 0)
|
||||
box3.border_width 2
|
||||
box3.add pixmapwid
|
||||
box3.add label
|
||||
button.add box3
|
||||
pixmapwid.show
|
||||
label.show
|
||||
box3.show
|
||||
|
||||
separator = Gtk::HSeparator::new()
|
||||
box1.pack_start(separator, FALSE, TRUE, 0)
|
||||
separator.show
|
||||
|
||||
box2 = Gtk::HBox::new(FALSE, 10)
|
||||
box2.border_width(10)
|
||||
box1.pack_start(box2, FALSE, TRUE, 0)
|
||||
box2.show
|
||||
|
||||
button = Gtk::Button::new("close")
|
||||
button.signal_connect("clicked") do
|
||||
window.destroy
|
||||
exit
|
||||
end
|
||||
box2.pack_start(button, TRUE, TRUE, 0)
|
||||
button.set_flags(Gtk::CAN_DEFAULT);
|
||||
button.grab_default
|
||||
button.show
|
||||
|
||||
window.show
|
||||
|
||||
Gtk::main()
|
|
@ -1,3 +0,0 @@
|
|||
MANIFEST
|
||||
depend
|
||||
kconv.c
|
|
@ -1 +0,0 @@
|
|||
kconv.o: kconv.c $(hdrdir)/ruby.h $(hdrdir)/config.h $(hdrdir)/defines.h
|
|
@ -1,3 +0,0 @@
|
|||
MANIFEST
|
||||
mandel.c
|
||||
tkmandel.rb
|
|
@ -1,59 +0,0 @@
|
|||
/************************************************
|
||||
|
||||
mandel.c -
|
||||
|
||||
$Author$
|
||||
|
||||
************************************************/
|
||||
|
||||
#include "ruby.h"
|
||||
#include "math.h"
|
||||
|
||||
static VALUE
|
||||
mandel(self, re, im, max)
|
||||
VALUE self;
|
||||
VALUE re;
|
||||
VALUE im;
|
||||
VALUE max;
|
||||
{
|
||||
double real, image;
|
||||
double z_real, z_image;
|
||||
double tmp_real;
|
||||
int maximum;
|
||||
int i;
|
||||
|
||||
Check_Type(re, T_FLOAT);
|
||||
Check_Type(im, T_FLOAT);
|
||||
Check_Type(max, T_FIXNUM);
|
||||
|
||||
real = RFLOAT(re)->value;
|
||||
image = RFLOAT(im)->value;
|
||||
maximum = FIX2INT(max);
|
||||
|
||||
/***
|
||||
z = c = Complex(re, im)
|
||||
for i in 0 .. $max_deapth
|
||||
z = (z * z) + c
|
||||
break if z.abs > 2
|
||||
end
|
||||
return i
|
||||
***/
|
||||
|
||||
z_real = real;
|
||||
z_image = image;
|
||||
for (i = 0; i < maximum; i++) {
|
||||
tmp_real = ((z_real * z_real) - (z_image * z_image)) + real;
|
||||
z_image = ((z_real * z_image) + (z_image * z_real)) + image;
|
||||
z_real = tmp_real;
|
||||
if ( ((z_real * z_real) + (z_image * z_image)) > 4.0 ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return INT2FIX(i);
|
||||
}
|
||||
|
||||
Init_mandel()
|
||||
{
|
||||
VALUE mMandel = rb_define_module("Mandel");
|
||||
rb_define_module_function(mMandel, "mandel", mandel, 3);
|
||||
}
|
|
@ -1,172 +0,0 @@
|
|||
# require "complex"
|
||||
require "mandel"
|
||||
require "tkclass"
|
||||
|
||||
DefaultMaxDepth = 30
|
||||
DefaultSX = -2.25
|
||||
DefaultSY = 1.75
|
||||
DefaultEX = 1.25
|
||||
DefaultEY = -1.75
|
||||
|
||||
def reset
|
||||
$max_depth = DefaultMaxDepth
|
||||
$s_re = DefaultSX
|
||||
$s_im = DefaultSY
|
||||
$e_re = DefaultEX
|
||||
$e_im = DefaultEY
|
||||
$dx = ($e_re - $s_re).abs / Width
|
||||
$dy = ($e_im - $s_im).abs / Height
|
||||
$photo.blank
|
||||
end
|
||||
|
||||
|
||||
Width = 400
|
||||
Height = 400
|
||||
|
||||
$c = Canvas.new {
|
||||
width Width
|
||||
height Height
|
||||
}
|
||||
$c.pack
|
||||
|
||||
$c_rect = Rectangle.new($c, 0, 0, Width+1, Height+1)
|
||||
$c_rect.fill "white"
|
||||
|
||||
$colors = []
|
||||
|
||||
def colors_init
|
||||
$colors = []
|
||||
for i in 0 .. 125
|
||||
$colors.push(format("#%02x%02x%02x", 250 - (i*2), i*2, 0))
|
||||
end
|
||||
for i in 0 .. 125
|
||||
$colors.push(format("#%02x%02x%02x", 0, 250 - (i*2), i*2))
|
||||
end
|
||||
$color_max = $colors.size - 1
|
||||
end
|
||||
|
||||
def zoom(a, b, c, d)
|
||||
center_x = (a + c) / 2
|
||||
center_y = (b + d) / 2
|
||||
size = (c - a).abs
|
||||
size = (d - b).abs if (size < (d - b).abs)
|
||||
size = 1 if (size < 1)
|
||||
zoom_rate = ((Width + Height) / 2).to_f / size
|
||||
$max_depth = ($max_depth.to_f * Math.sqrt(Math.sqrt(Math.sqrt(zoom_rate)))).to_i
|
||||
|
||||
move_x_rate = (center_x - (Width / 2)).to_f / (Width / 2)
|
||||
move_y_rate = (center_y - (Height / 2)).to_f / (Height / 2)
|
||||
|
||||
center_re = ($s_re + $e_re) / 2
|
||||
center_im = ($s_im + $e_im) / 2
|
||||
c_size_re = ($e_re - $s_re).abs
|
||||
c_size_im = ($e_im - $s_im).abs
|
||||
|
||||
center_re = center_re + (move_x_rate * (c_size_re / 2))
|
||||
center_im = center_im - (move_y_rate * (c_size_im / 2))
|
||||
|
||||
$s_re = center_re - ((c_size_re / 2) / zoom_rate)
|
||||
$s_im = center_im + ((c_size_im / 2) / zoom_rate)
|
||||
$e_re = center_re + ((c_size_re / 2) / zoom_rate)
|
||||
$e_im = center_im - ((c_size_im / 2) / zoom_rate)
|
||||
|
||||
$dx = ($e_re - $s_re).abs / Width
|
||||
$dy = ($e_im - $s_im).abs / Height
|
||||
p [$s_re, $dx, $s_im, $dy]
|
||||
end
|
||||
|
||||
|
||||
def mandel(x, y)
|
||||
re = $s_re + ($dx * x)
|
||||
im = $s_im - ($dy * y)
|
||||
# z = c = Complex(re, im)
|
||||
# for i in 0 .. $max_depth
|
||||
# z = (z * z) + c
|
||||
# break if z.abs > 2
|
||||
# end
|
||||
# return i
|
||||
return Mandel.mandel(re, im, $max_depth)
|
||||
end
|
||||
|
||||
$buf = "{"+" "*Width+"}"
|
||||
def calc
|
||||
$c.update
|
||||
return if $current_rect
|
||||
depth = 0
|
||||
|
||||
for x in 0 .. Width - 1
|
||||
depth = mandel(x, $calc_y)
|
||||
if depth >= $max_depth
|
||||
$buf[x*8+1,7] = "#000000"
|
||||
else
|
||||
$buf[x*8+1,7] = $colors[$color_max * depth / $max_depth]
|
||||
end
|
||||
end
|
||||
$photo.put($buf, 0, $calc_y)
|
||||
|
||||
$calc_y += 1
|
||||
if (($calc_y % 20) == 0)
|
||||
print "#{($calc_y * 100 / Height)}% done. -- depth #{$max_depth}\n"
|
||||
# $mandel.image $photo
|
||||
end
|
||||
|
||||
if ($calc_y > Height - 1)
|
||||
$calc_y = StartCalcY
|
||||
$calc_on = false
|
||||
# exit
|
||||
end
|
||||
|
||||
if $calc_on
|
||||
Tk.after(1) { calc() }
|
||||
end
|
||||
end
|
||||
|
||||
$photo = TkPhotoImage.new({'width'=>Width, 'height'=>Height})
|
||||
$mandel = TkcImage.new($c, Width/2, Height/2) { image $photo }
|
||||
reset()
|
||||
colors_init()
|
||||
$calc_y = StartCalcY = 0
|
||||
$calc_on = true
|
||||
calc()
|
||||
|
||||
def clear
|
||||
# $mandel.destroy if $mandel
|
||||
$calc_y = StartCalcY
|
||||
end
|
||||
|
||||
$start_x = $start_y = 0
|
||||
$current_rect = nil
|
||||
|
||||
def do_press(x, y)
|
||||
$start_x = x
|
||||
$start_y = y
|
||||
$current_rect = Rectangle.new($c, x, y, x, y) { outline "white" }
|
||||
end
|
||||
|
||||
def do_motion(x, y)
|
||||
if $current_rect
|
||||
$current_rect.coords $start_x, $start_y, x, y
|
||||
end
|
||||
end
|
||||
|
||||
def do_release(x, y)
|
||||
if $current_rect
|
||||
$current_rect.coords $start_x, $start_y, x, y
|
||||
$current_rect.destroy
|
||||
$current_rect = nil
|
||||
clear()
|
||||
$calc_on = true
|
||||
zoom($start_x, $start_y, x, y)
|
||||
calc()
|
||||
end
|
||||
end
|
||||
|
||||
$c.bind("1", proc{|e| do_press e.x, e.y})
|
||||
$c.bind("B1-Motion", proc{|x, y| do_motion x, y}, "%x %y")
|
||||
$c.bind("ButtonRelease-1", proc{|x, y| do_release x, y}, "%x %y")
|
||||
|
||||
begin
|
||||
Tk.mainloop
|
||||
ensure
|
||||
# File.delete("#tmpmandel#.gif")
|
||||
end
|
|
@ -1,2 +0,0 @@
|
|||
marshal.o: marshal.c ../../ruby.h ../../config.h ../../defines.h ../../io.h \
|
||||
../../st.h
|
|
@ -1 +0,0 @@
|
|||
create_makefile("marshal")
|
|
@ -1,850 +0,0 @@
|
|||
/************************************************
|
||||
|
||||
marshal.c -
|
||||
|
||||
$Author$
|
||||
$Revision$
|
||||
$Date$
|
||||
created at: Thu Apr 27 16:30:01 JST 1995
|
||||
|
||||
************************************************/
|
||||
|
||||
#include "ruby.h"
|
||||
#include "io.h"
|
||||
#include "st.h"
|
||||
|
||||
#define MARSHAL_MAJOR 4
|
||||
#define MARSHAL_MINOR 0
|
||||
|
||||
#define TYPE_NIL '0'
|
||||
#define TYPE_TRUE 'T'
|
||||
#define TYPE_FALSE 'F'
|
||||
#define TYPE_FIXNUM 'i'
|
||||
|
||||
#define TYPE_UCLASS 'C'
|
||||
#define TYPE_OBJECT 'o'
|
||||
#define TYPE_USERDEF 'u'
|
||||
#define TYPE_FLOAT 'f'
|
||||
#define TYPE_BIGNUM 'l'
|
||||
#define TYPE_STRING '"'
|
||||
#define TYPE_REGEXP '/'
|
||||
#define TYPE_ARRAY '['
|
||||
#define TYPE_HASH '{'
|
||||
#define TYPE_STRUCT 'S'
|
||||
#define TYPE_MODULE 'M'
|
||||
|
||||
#define TYPE_SYMBOL ':'
|
||||
#define TYPE_SYMLINK ';'
|
||||
|
||||
#define TYPE_LINK '@'
|
||||
|
||||
extern VALUE cString;
|
||||
extern VALUE cRegexp;
|
||||
extern VALUE cArray;
|
||||
extern VALUE cHash;
|
||||
|
||||
VALUE rb_path2class();
|
||||
|
||||
static ID s_dump, s_load;
|
||||
|
||||
struct dump_arg {
|
||||
VALUE obj;
|
||||
FILE *fp;
|
||||
VALUE str;
|
||||
st_table *symbol;
|
||||
st_table *data;
|
||||
};
|
||||
|
||||
struct dump_call_arg {
|
||||
VALUE obj;
|
||||
struct dump_arg *arg;
|
||||
int limit;
|
||||
};
|
||||
|
||||
static void w_long _((long, struct dump_arg*));
|
||||
|
||||
static void
|
||||
w_byte(c, arg)
|
||||
char c;
|
||||
struct dump_arg *arg;
|
||||
{
|
||||
if (arg->fp) putc(c, arg->fp);
|
||||
else str_cat(arg->str, (UCHAR*)&c, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
w_bytes(s, n, arg)
|
||||
char *s;
|
||||
int n;
|
||||
struct dump_arg *arg;
|
||||
{
|
||||
w_long(n, arg);
|
||||
if (arg->fp) {
|
||||
fwrite(s, 1, n, arg->fp);
|
||||
}
|
||||
else {
|
||||
str_cat(arg->str, s, n);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
w_short(x, arg)
|
||||
int x;
|
||||
struct dump_arg *arg;
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<sizeof(USHORT); i++) {
|
||||
w_byte((x >> (i*8)) & 0xff, arg);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
w_long(x, arg)
|
||||
long x;
|
||||
struct dump_arg *arg;
|
||||
{
|
||||
char buf[sizeof(long)+1];
|
||||
int i, len = 0;
|
||||
|
||||
if (x == 0) {
|
||||
w_byte(0, arg);
|
||||
return;
|
||||
}
|
||||
for (i=1;i<sizeof(long)+1;i++) {
|
||||
buf[i] = x & 0xff;
|
||||
x = RSHIFT(x,8);
|
||||
if (x == 0) {
|
||||
buf[0] = i;
|
||||
break;
|
||||
}
|
||||
if (x == -1) {
|
||||
buf[0] = -i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
len = i;
|
||||
for (i=0;i<=len;i++) {
|
||||
w_byte(buf[i], arg);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
w_float(d, arg)
|
||||
double d;
|
||||
struct dump_arg *arg;
|
||||
{
|
||||
char buf[100];
|
||||
|
||||
sprintf(buf, "%.12g", d);
|
||||
w_bytes(buf, strlen(buf), arg);
|
||||
}
|
||||
|
||||
static void
|
||||
w_symbol(id, arg)
|
||||
ID id;
|
||||
struct dump_arg *arg;
|
||||
{
|
||||
char *sym = rb_id2name(id);
|
||||
int num;
|
||||
|
||||
if (st_lookup(arg->symbol, id, &num)) {
|
||||
w_byte(TYPE_SYMLINK, arg);
|
||||
w_long(num, arg);
|
||||
}
|
||||
else {
|
||||
w_byte(TYPE_SYMBOL, arg);
|
||||
w_bytes(sym, strlen(sym), arg);
|
||||
st_insert(arg->symbol, id, arg->symbol->num_entries);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
w_unique(s, arg)
|
||||
char *s;
|
||||
struct dump_arg *arg;
|
||||
{
|
||||
w_symbol(rb_intern(s), arg);
|
||||
}
|
||||
|
||||
static void w_object _((VALUE,struct dump_arg*,int));
|
||||
extern VALUE cIO, cBignum, cStruct;
|
||||
|
||||
static int
|
||||
hash_each(key, value, arg)
|
||||
VALUE key, value;
|
||||
struct dump_call_arg *arg;
|
||||
{
|
||||
w_object(key, arg->arg, arg->limit);
|
||||
w_object(value, arg->arg, arg->limit);
|
||||
return ST_CONTINUE;
|
||||
}
|
||||
|
||||
static int
|
||||
obj_each(id, value, arg)
|
||||
ID id;
|
||||
VALUE value;
|
||||
struct dump_call_arg *arg;
|
||||
{
|
||||
w_symbol(id, arg->arg);
|
||||
w_object(value, arg->arg, arg->limit);
|
||||
return ST_CONTINUE;
|
||||
}
|
||||
|
||||
static void
|
||||
w_uclass(obj, class, arg)
|
||||
VALUE obj, class;
|
||||
struct dump_arg *arg;
|
||||
{
|
||||
if (CLASS_OF(obj) != class) {
|
||||
w_byte(TYPE_UCLASS, arg);
|
||||
w_unique(rb_class2name(CLASS_OF(obj)), arg);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
w_object(obj, arg, limit)
|
||||
VALUE obj;
|
||||
struct dump_arg *arg;
|
||||
int limit;
|
||||
{
|
||||
int n;
|
||||
struct dump_call_arg c_arg;
|
||||
|
||||
if (limit == 0) {
|
||||
Fail("exceed depth limit");
|
||||
}
|
||||
limit--;
|
||||
c_arg.limit = limit;
|
||||
c_arg.arg = arg;
|
||||
|
||||
if (obj == Qnil) {
|
||||
w_byte(TYPE_NIL, arg);
|
||||
}
|
||||
else if (obj == TRUE) {
|
||||
w_byte(TYPE_TRUE, arg);
|
||||
}
|
||||
else if (obj == FALSE) {
|
||||
w_byte(TYPE_FALSE, arg);
|
||||
}
|
||||
else if (FIXNUM_P(obj)) {
|
||||
#if SIZEOF_LONG <= 4
|
||||
w_byte(TYPE_FIXNUM, arg);
|
||||
w_long(FIX2INT(obj), arg);
|
||||
#else
|
||||
if (RSHIFT(obj, 32) == 0 || RSHIFT(obj, 32) == -1) {
|
||||
w_byte(TYPE_FIXNUM, arg);
|
||||
w_long(FIX2INT(obj), arg);
|
||||
}
|
||||
else {
|
||||
obj = int2big(FIX2INT(obj));
|
||||
goto write_bignum;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
int num;
|
||||
|
||||
if (st_lookup(arg->data, obj, &num)) {
|
||||
w_byte(TYPE_LINK, arg);
|
||||
w_long(num, arg);
|
||||
return;
|
||||
}
|
||||
st_insert(arg->data, obj, arg->data->num_entries);
|
||||
if (rb_respond_to(obj, s_dump)) {
|
||||
VALUE v;
|
||||
|
||||
w_byte(TYPE_USERDEF, arg);
|
||||
w_unique(rb_class2name(CLASS_OF(obj)), arg);
|
||||
v = rb_funcall(obj, s_dump, 1, limit);
|
||||
if (TYPE(v) != T_STRING) {
|
||||
TypeError("_dump_to must return String");
|
||||
}
|
||||
w_bytes(RSTRING(v)->ptr, RSTRING(v)->len, arg);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (BUILTIN_TYPE(obj)) {
|
||||
case T_MODULE:
|
||||
case T_CLASS:
|
||||
w_byte(TYPE_MODULE, arg);
|
||||
{
|
||||
VALUE path = rb_class_path(obj);
|
||||
w_bytes(RSTRING(path)->ptr, RSTRING(path)->len, arg);
|
||||
}
|
||||
return;
|
||||
|
||||
case T_FLOAT:
|
||||
w_byte(TYPE_FLOAT, arg);
|
||||
w_float(RFLOAT(obj)->value, arg);
|
||||
return;
|
||||
|
||||
case T_BIGNUM:
|
||||
write_bignum:
|
||||
w_byte(TYPE_BIGNUM, arg);
|
||||
{
|
||||
char sign = RBIGNUM(obj)->sign?'+':'-';
|
||||
int len = RBIGNUM(obj)->len;
|
||||
USHORT *d = RBIGNUM(obj)->digits;
|
||||
|
||||
w_byte(sign, arg);
|
||||
w_long(len, arg);
|
||||
while (len--) {
|
||||
w_short(*d, arg);
|
||||
d++;
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
case T_STRING:
|
||||
w_uclass(obj, cString, arg);
|
||||
w_byte(TYPE_STRING, arg);
|
||||
w_bytes(RSTRING(obj)->ptr, RSTRING(obj)->len, arg);
|
||||
return;
|
||||
|
||||
case T_REGEXP:
|
||||
w_uclass(obj, cRegexp, arg);
|
||||
w_byte(TYPE_REGEXP, arg);
|
||||
w_bytes(RREGEXP(obj)->str, RREGEXP(obj)->len, arg);
|
||||
w_byte(FL_TEST(obj, FL_USER1), arg);
|
||||
return;
|
||||
|
||||
case T_ARRAY:
|
||||
w_uclass(obj, cArray, arg);
|
||||
w_byte(TYPE_ARRAY, arg);
|
||||
{
|
||||
int len = RARRAY(obj)->len;
|
||||
VALUE *ptr = RARRAY(obj)->ptr;
|
||||
|
||||
w_long(len, arg);
|
||||
while (len--) {
|
||||
w_object(*ptr, arg, limit);
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case T_HASH:
|
||||
w_uclass(obj, cHash, arg);
|
||||
w_byte(TYPE_HASH, arg);
|
||||
w_long(RHASH(obj)->tbl->num_entries, arg);
|
||||
st_foreach(RHASH(obj)->tbl, hash_each, &c_arg);
|
||||
break;
|
||||
|
||||
case T_STRUCT:
|
||||
w_byte(TYPE_STRUCT, arg);
|
||||
{
|
||||
int len = RSTRUCT(obj)->len;
|
||||
char *path = rb_class2name(CLASS_OF(obj));
|
||||
VALUE mem;
|
||||
int i;
|
||||
|
||||
w_unique(path, arg);
|
||||
w_long(len, arg);
|
||||
mem = rb_ivar_get(CLASS_OF(obj), rb_intern("__member__"));
|
||||
if (mem == Qnil) {
|
||||
Fatal("non-initialized struct");
|
||||
}
|
||||
for (i=0; i<len; i++) {
|
||||
w_symbol(FIX2INT(RARRAY(mem)->ptr[i]), arg);
|
||||
w_object(RSTRUCT(obj)->ptr[i], arg, limit);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case T_OBJECT:
|
||||
w_byte(TYPE_OBJECT, arg);
|
||||
{
|
||||
VALUE class = CLASS_OF(obj);
|
||||
char *path;
|
||||
|
||||
if (FL_TEST(class, FL_SINGLETON)) {
|
||||
TypeError("singleton can't be dumped");
|
||||
}
|
||||
path = rb_class2name(class);
|
||||
w_unique(path, arg);
|
||||
if (ROBJECT(obj)->iv_tbl) {
|
||||
w_long(ROBJECT(obj)->iv_tbl->num_entries, arg);
|
||||
st_foreach(ROBJECT(obj)->iv_tbl, obj_each, &c_arg);
|
||||
}
|
||||
else {
|
||||
w_long(0, arg);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
TypeError("can't dump %s", rb_class2name(CLASS_OF(obj)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static VALUE
|
||||
dump(arg)
|
||||
struct dump_call_arg *arg;
|
||||
{
|
||||
w_object(arg->obj, arg->arg, arg->limit);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
dump_ensure(arg)
|
||||
struct dump_arg *arg;
|
||||
{
|
||||
st_free_table(arg->symbol);
|
||||
st_free_table(arg->data);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
marshal_dump(argc, argv)
|
||||
int argc;
|
||||
VALUE argv;
|
||||
{
|
||||
VALUE obj, port, a1, a2;
|
||||
int limit = -1;
|
||||
extern VALUE cIO;
|
||||
struct dump_arg arg;
|
||||
struct dump_call_arg c_arg;
|
||||
|
||||
port = 0;
|
||||
rb_scan_args(argc, argv, "12", &obj, &a1, &a2);
|
||||
if (argc == 3) {
|
||||
limit = NUM2INT(a2);
|
||||
port = a1;
|
||||
}
|
||||
else if (argc == 2) {
|
||||
if (FIXNUM_P(a1)) limit = FIX2INT(a1);
|
||||
else port = a1;
|
||||
}
|
||||
if (port) {
|
||||
if (obj_is_kind_of(port, cIO)) {
|
||||
OpenFile *fptr;
|
||||
|
||||
io_binmode(port);
|
||||
GetOpenFile(port, fptr);
|
||||
io_writable(fptr);
|
||||
arg.fp = (fptr->f2) ? fptr->f2 : fptr->f;
|
||||
}
|
||||
else {
|
||||
TypeError("instance of IO needed");
|
||||
}
|
||||
}
|
||||
else {
|
||||
arg.fp = 0;
|
||||
port = str_new(0, 0);
|
||||
arg.str = port;
|
||||
}
|
||||
|
||||
arg.symbol = st_init_numtable();
|
||||
arg.data = st_init_numtable();
|
||||
c_arg.obj = obj;
|
||||
c_arg.arg = &arg;
|
||||
c_arg.limit = limit;
|
||||
|
||||
w_byte(MARSHAL_MAJOR, &arg);
|
||||
w_byte(MARSHAL_MINOR, &arg);
|
||||
|
||||
rb_ensure(dump, &c_arg, dump_ensure, &arg);
|
||||
|
||||
return port;
|
||||
}
|
||||
|
||||
struct load_arg {
|
||||
FILE *fp;
|
||||
UCHAR *ptr, *end;
|
||||
st_table *symbol;
|
||||
st_table *data;
|
||||
};
|
||||
|
||||
static int
|
||||
r_byte(arg)
|
||||
struct load_arg *arg;
|
||||
{
|
||||
if (arg->fp) return getc(arg->fp);
|
||||
if (arg->ptr < arg->end) return *arg->ptr++;
|
||||
return EOF;
|
||||
}
|
||||
|
||||
static USHORT
|
||||
r_short(arg)
|
||||
struct load_arg *arg;
|
||||
{
|
||||
USHORT x;
|
||||
int i;
|
||||
|
||||
x = 0;
|
||||
for (i=0; i<sizeof(USHORT); i++) {
|
||||
x |= r_byte(arg)<<(i*8);
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
static void
|
||||
long_toobig(size)
|
||||
int size;
|
||||
{
|
||||
TypeError("long too big for this architecture (size %d, given %d)",
|
||||
sizeof(long), size);
|
||||
}
|
||||
|
||||
static long
|
||||
r_long(arg)
|
||||
struct load_arg *arg;
|
||||
{
|
||||
int c = r_byte(arg), i;
|
||||
register long x;
|
||||
|
||||
if (c == 0) return 0;
|
||||
if (c > 0) {
|
||||
if (c > sizeof(long)) long_toobig((int)c);
|
||||
x = 0;
|
||||
for (i=0;i<c;i++) {
|
||||
x |= (long)r_byte(arg) << (8*i);
|
||||
}
|
||||
}
|
||||
else if (c < 0) {
|
||||
c = -c;
|
||||
if (c > sizeof(long)) long_toobig((int)c);
|
||||
x = -1;
|
||||
for (i=0;i<c;i++) {
|
||||
x &= ~(0xff << (8*i));
|
||||
x |= (long)r_byte(arg) << (8*i);
|
||||
}
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
#define r_bytes(s, arg) \
|
||||
(s = (char*)r_long(arg), r_bytes0(&s,ALLOCA_N(char,(long)s),(long)s,arg))
|
||||
|
||||
static int
|
||||
r_bytes0(sp, s, len, arg)
|
||||
char **sp, *s;
|
||||
int len;
|
||||
struct load_arg *arg;
|
||||
{
|
||||
if (arg->fp) {
|
||||
len = fread(s, 1, len, arg->fp);
|
||||
}
|
||||
else {
|
||||
if (arg->ptr + len > arg->end) {
|
||||
len = arg->end - arg->ptr;
|
||||
}
|
||||
memcpy(s, arg->ptr, len);
|
||||
arg->ptr += len;
|
||||
}
|
||||
|
||||
(s)[len] = '\0';
|
||||
*sp = s;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static ID
|
||||
r_symbol(arg)
|
||||
struct load_arg *arg;
|
||||
{
|
||||
char *buf;
|
||||
ID id;
|
||||
char type;
|
||||
|
||||
if (r_byte(arg) == TYPE_SYMLINK) {
|
||||
int num = r_long(arg);
|
||||
|
||||
if (st_lookup(arg->symbol, num, &id)) {
|
||||
return id;
|
||||
}
|
||||
TypeError("bad symbol");
|
||||
}
|
||||
r_bytes(buf, arg);
|
||||
id = rb_intern(buf);
|
||||
st_insert(arg->symbol, arg->symbol->num_entries, id);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
static char*
|
||||
r_unique(arg)
|
||||
struct load_arg *arg;
|
||||
{
|
||||
return rb_id2name(r_symbol(arg));
|
||||
}
|
||||
|
||||
static VALUE
|
||||
r_string(arg)
|
||||
struct load_arg *arg;
|
||||
{
|
||||
char *buf;
|
||||
int len = r_bytes(buf, arg);
|
||||
|
||||
return str_taint(str_new(buf, len));
|
||||
}
|
||||
|
||||
static VALUE
|
||||
r_regist(v, arg)
|
||||
VALUE v;
|
||||
struct load_arg *arg;
|
||||
{
|
||||
st_insert(arg->data, arg->data->num_entries, v);
|
||||
return v;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
r_object(arg)
|
||||
struct load_arg *arg;
|
||||
{
|
||||
VALUE v;
|
||||
int type = r_byte(arg);
|
||||
|
||||
switch (type) {
|
||||
case EOF:
|
||||
eof_error();
|
||||
return Qnil;
|
||||
|
||||
case TYPE_LINK:
|
||||
if (st_lookup(arg->data, r_long(arg), &v)) {
|
||||
return v;
|
||||
}
|
||||
ArgError("dump format error (unlinked)");
|
||||
break;
|
||||
|
||||
case TYPE_UCLASS:
|
||||
{
|
||||
VALUE c = rb_path2class(r_unique(arg));
|
||||
v = r_object(arg);
|
||||
if (rb_special_const_p(v)) {
|
||||
ArgError("dump format error (user class)");
|
||||
}
|
||||
RBASIC(v)->class = c;
|
||||
return v;
|
||||
}
|
||||
|
||||
case TYPE_NIL:
|
||||
return Qnil;
|
||||
|
||||
case TYPE_TRUE:
|
||||
return TRUE;
|
||||
|
||||
case TYPE_FALSE:
|
||||
return FALSE;
|
||||
|
||||
case TYPE_FIXNUM:
|
||||
{
|
||||
int i = r_long(arg);
|
||||
return INT2FIX(i);
|
||||
}
|
||||
|
||||
case TYPE_FLOAT:
|
||||
{
|
||||
#ifndef atof
|
||||
double atof();
|
||||
#endif
|
||||
char *buf;
|
||||
|
||||
r_bytes(buf, arg);
|
||||
v = float_new(atof(buf));
|
||||
return r_regist(v, arg);
|
||||
}
|
||||
|
||||
case TYPE_BIGNUM:
|
||||
{
|
||||
int len;
|
||||
USHORT *digits;
|
||||
|
||||
NEWOBJ(big, struct RBignum);
|
||||
OBJSETUP(big, cBignum, T_BIGNUM);
|
||||
big->sign = (r_byte(arg) == '+');
|
||||
big->len = len = r_long(arg);
|
||||
big->digits = digits = ALLOC_N(USHORT, len);
|
||||
while (len--) {
|
||||
*digits++ = r_short(arg);
|
||||
}
|
||||
big = RBIGNUM(big_norm((VALUE)big));
|
||||
if (TYPE(big) == T_BIGNUM) {
|
||||
r_regist(big, arg);
|
||||
}
|
||||
return (VALUE)big;
|
||||
}
|
||||
|
||||
case TYPE_STRING:
|
||||
return r_regist(r_string(arg), arg);
|
||||
|
||||
case TYPE_REGEXP:
|
||||
{
|
||||
char *buf;
|
||||
int len = r_bytes(buf, arg);
|
||||
int ci = r_byte(arg);
|
||||
return r_regist(reg_new(buf, len, ci), arg);
|
||||
}
|
||||
|
||||
case TYPE_ARRAY:
|
||||
{
|
||||
volatile int len = r_long(arg);
|
||||
v = ary_new2(len);
|
||||
r_regist(v, arg);
|
||||
while (len--) {
|
||||
ary_push(v, r_object(arg));
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
case TYPE_HASH:
|
||||
{
|
||||
int len = r_long(arg);
|
||||
|
||||
v = hash_new();
|
||||
r_regist(v, arg);
|
||||
while (len--) {
|
||||
VALUE key = r_object(arg);
|
||||
VALUE value = r_object(arg);
|
||||
hash_aset(v, key, value);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
case TYPE_STRUCT:
|
||||
{
|
||||
VALUE class, mem, values;
|
||||
int i, len;
|
||||
int num = arg->data->num_entries;
|
||||
|
||||
class = rb_path2class(r_unique(arg));
|
||||
mem = rb_ivar_get(class, rb_intern("__member__"));
|
||||
if (mem == Qnil) {
|
||||
Fatal("non-initialized struct");
|
||||
}
|
||||
len = r_long(arg);
|
||||
|
||||
values = ary_new2(len);
|
||||
for (i=0; i<len; i++) {
|
||||
ary_push(values, Qnil);
|
||||
}
|
||||
v = struct_alloc(class, values);
|
||||
r_regist(v, arg);
|
||||
for (i=0; i<len; i++) {
|
||||
ID slot = r_symbol(arg);
|
||||
if (RARRAY(mem)->ptr[i] != INT2FIX(slot))
|
||||
TypeError("struct not compatible");
|
||||
struct_aset(v, INT2FIX(i), r_object(arg));
|
||||
}
|
||||
return v;
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_USERDEF:
|
||||
{
|
||||
VALUE class;
|
||||
int len;
|
||||
|
||||
class = rb_path2class(r_unique(arg));
|
||||
if (rb_respond_to(class, s_load)) {
|
||||
v = rb_funcall(class, s_load, 1, r_string(arg));
|
||||
return r_regist(v, arg);
|
||||
}
|
||||
TypeError("class %s needs to have method `_load_from'",
|
||||
rb_class2name(class));
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_OBJECT:
|
||||
{
|
||||
VALUE class;
|
||||
int len;
|
||||
|
||||
class = rb_path2class(r_unique(arg));
|
||||
len = r_long(arg);
|
||||
v = obj_alloc(class);
|
||||
r_regist(v, arg);
|
||||
if (len > 0) {
|
||||
while (len--) {
|
||||
ID id = r_symbol(arg);
|
||||
VALUE val = r_object(arg);
|
||||
rb_ivar_set(v, id, val);
|
||||
}
|
||||
}
|
||||
return v;
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_MODULE:
|
||||
{
|
||||
char *buf;
|
||||
r_bytes(buf, arg);
|
||||
return rb_path2class(buf);
|
||||
}
|
||||
|
||||
default:
|
||||
ArgError("dump format error(0x%x)", type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static VALUE
|
||||
load(arg)
|
||||
struct load_arg *arg;
|
||||
{
|
||||
return r_object(arg);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
load_ensure(arg)
|
||||
struct load_arg *arg;
|
||||
{
|
||||
st_free_table(arg->symbol);
|
||||
st_free_table(arg->data);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
marshal_load(self, port)
|
||||
VALUE self, port;
|
||||
{
|
||||
FILE *fp;
|
||||
int major;
|
||||
VALUE v;
|
||||
OpenFile *fptr;
|
||||
struct load_arg arg;
|
||||
|
||||
if (TYPE(port) == T_STRING) {
|
||||
arg.fp = 0;
|
||||
arg.ptr = RSTRING(port)->ptr;
|
||||
arg.end = arg.ptr + RSTRING(port)->len;
|
||||
}
|
||||
else {
|
||||
if (obj_is_kind_of(port, cIO)) {
|
||||
io_binmode(port);
|
||||
GetOpenFile(port, fptr);
|
||||
io_readable(fptr);
|
||||
arg.fp = fptr->f;
|
||||
}
|
||||
else {
|
||||
TypeError("instance of IO needed");
|
||||
}
|
||||
}
|
||||
|
||||
major = r_byte(&arg);
|
||||
if (major == MARSHAL_MAJOR) {
|
||||
if (r_byte(&arg) != MARSHAL_MINOR) {
|
||||
Warning("Old marshal file format (can be read)");
|
||||
}
|
||||
arg.symbol = st_init_numtable();
|
||||
arg.data = st_init_numtable();
|
||||
v = rb_ensure(load, &arg, load_ensure, &arg);
|
||||
}
|
||||
else {
|
||||
TypeError("Old marshal file format (can't read)");
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
Init_marshal()
|
||||
{
|
||||
VALUE mMarshal = rb_define_module("Marshal");
|
||||
|
||||
s_dump = rb_intern("_dump_to");
|
||||
s_load = rb_intern("_load_from");
|
||||
rb_define_module_function(mMarshal, "dump", marshal_dump, -1);
|
||||
rb_define_module_function(mMarshal, "load", marshal_load, 1);
|
||||
rb_define_module_function(mMarshal, "restore", marshal_load, 1);
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
.\" marshal.doc - -*- Indented-Text -*- created at: Tue May 16 12:18:08 JST 1995
|
||||
|
||||
** Marshal(モジュール)
|
||||
|
||||
rubyオブジェクトをファイルに書き出したり,読みも度したりする機能を提供
|
||||
するモジュール.大部分のクラスのインスタンスを書き出す事ができるが,ファ
|
||||
イルへの不可能なクラスも存在し(例:IO),そのようなクラスを書き出そうと
|
||||
すると例外を発生させる.
|
||||
|
||||
Methods:
|
||||
Single Methods:
|
||||
|
||||
dump(obj, port[, limit])
|
||||
|
||||
objを再帰的にファイルに書き出す.ファイルに書き出せないクラスのイ
|
||||
ンスタンスをファイルに書き出そうとすると例外を発生させる.ファイル
|
||||
に書き出せないクラスは以下の通り.
|
||||
|
||||
Class, Module, Data
|
||||
|
||||
また,これらのクラスを間接的に指すクラス(例えばIOのサブクラス)など
|
||||
も書き出せない.portはIO(またはそのサブクラス)のインスタンスを指定
|
||||
する.
|
||||
|
||||
出力するオブジェクトがメソッド`_dump_to'を定義している場合には,ファ
|
||||
イル出力はそのメソッドを使って行われる.メソッド`_dump_to'は引数と
|
||||
して出力先のファイルオブジェクトを受け取る.インスタンスがメソッド
|
||||
`_dump_to'を持つクラスは必ず同じフォーマットを読み戻す特異メソッド
|
||||
`_load_from'を定義する必要がある.
|
||||
|
||||
limitを指定した場合,limit段以上深くリンクしたオブジェクトをダンプ
|
||||
できない(デフォルトは100レベル)。負のlimitを指定すると深さチェック
|
||||
を行わない。
|
||||
|
||||
dumps(obj)
|
||||
|
||||
dump()がファイルに書き出すのと同じ内容を含む文字列を返す.
|
||||
|
||||
load(port)
|
||||
|
||||
portからオブジェクトを読み込んで来て,元のオブジェクトと同じ状態を
|
||||
もつオブジェクトを生成する.portは文字列かIO(またはそのサブクラス)
|
||||
のインスタンスである.
|
||||
|
||||
-------------------------------------------------------
|
||||
Local variables:
|
||||
fill-column: 70
|
||||
end:
|
|
@ -1,6 +1,7 @@
|
|||
MANIFEST
|
||||
depend
|
||||
md5.doc
|
||||
md5.txt
|
||||
md5.txt.jp
|
||||
md5.h
|
||||
md5c.c
|
||||
md5init.c
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
md5c.o: md5c.c md5.h
|
||||
md5init.o: md5init.c $(hdrdir)/ruby.h $(hdrdir)/config.h $(hdrdir)/defines.h md5.h
|
||||
md5init.o: md5init.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h md5.h
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
.\" md5.doc - -*- Indented-Text -*- created at: Fri Aug 2 12:01:27 JST 1996
|
||||
|
||||
** MD5(Class)
|
||||
|
||||
A class to implement MD5 Message-Digest Algorithm by RSA Data
|
||||
Security, Inc., described in RFC1321.
|
||||
|
||||
SuperClass: Object
|
||||
|
||||
Class Methods:
|
||||
|
||||
new([str])
|
||||
md5([str])
|
||||
|
||||
creates a new MD5 object. If a string argument is given, it
|
||||
is added to the object. (see update.)
|
||||
|
||||
Methods:
|
||||
|
||||
clone
|
||||
|
||||
copies the MD5 object.
|
||||
|
||||
digest
|
||||
|
||||
returns have value of the added strings as a 16 bytes string.
|
||||
|
||||
update(str)
|
||||
|
||||
Update the MD5 object with the string. Repeated calls are
|
||||
equivalent to a single call with the concatenation of all the
|
||||
arguments, i.e. m.update(a); m.update(b) is equivalent to
|
||||
m.update(a+b).
|
||||
|
||||
-------------------------------------------------------
|
||||
Local variables:
|
||||
fill-column: 70
|
||||
end:
|
|
@ -28,7 +28,8 @@ Methods:
|
|||
|
||||
update(str)
|
||||
|
||||
keyをキーとする値を返す.
|
||||
MD5オブジェクトに文字列を追加する。複数回updateを呼ぶことは文
|
||||
字列を連結してupdateを呼ぶことと等しい.
|
||||
|
||||
-------------------------------------------------------
|
||||
Local variables:
|
|
@ -29,8 +29,9 @@ md5_update(obj, str)
|
|||
Data_Get_Struct(obj, MD5_CTX, md5);
|
||||
MD5Update(md5, str->ptr, str->len);
|
||||
|
||||
return Qnil;
|
||||
return obj;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
md5_digest(obj)
|
||||
VALUE obj;
|
||||
|
@ -45,11 +46,29 @@ md5_digest(obj)
|
|||
return rb_str_new(digest, 16);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
md5_hexdigest(obj)
|
||||
VALUE obj;
|
||||
{
|
||||
MD5_CTX *md5, ctx;
|
||||
unsigned char digest[16];
|
||||
char buf[33];
|
||||
int i;
|
||||
|
||||
Data_Get_Struct(obj, MD5_CTX, md5);
|
||||
ctx = *md5;
|
||||
MD5Final(digest, &ctx);
|
||||
|
||||
for (i=0; i<16; i++) {
|
||||
sprintf(buf+i*2, "%02x", digest[i]);
|
||||
}
|
||||
return rb_str_new(buf, 32);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
md5_clone(obj)
|
||||
VALUE obj;
|
||||
{
|
||||
VALUE clone;
|
||||
MD5_CTX *md5, *md5_new;
|
||||
|
||||
Data_Get_Struct(obj, MD5_CTX, md5);
|
||||
|
@ -65,7 +84,6 @@ md5_new(argc, argv, class)
|
|||
VALUE* argv;
|
||||
VALUE class;
|
||||
{
|
||||
int i;
|
||||
VALUE arg, obj;
|
||||
MD5_CTX *md5;
|
||||
|
||||
|
@ -77,11 +95,12 @@ md5_new(argc, argv, class)
|
|||
if (!NIL_P(arg)) {
|
||||
md5_update(obj, arg);
|
||||
}
|
||||
rb_obj_call_init(obj);
|
||||
rb_obj_call_init(obj, argc, argv);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
void
|
||||
Init_md5()
|
||||
{
|
||||
cMD5 = rb_define_class("MD5", rb_cObject);
|
||||
|
@ -90,5 +109,6 @@ Init_md5()
|
|||
|
||||
rb_define_method(cMD5, "update", md5_update, 1);
|
||||
rb_define_method(cMD5, "digest", md5_digest, 0);
|
||||
rb_define_method(cMD5, "hexdigest", md5_hexdigest, 0);
|
||||
rb_define_method(cMD5, "clone", md5_clone, 0);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
MANIFEST
|
||||
depend
|
||||
extconf.rb
|
||||
lib/kconv.rb
|
||||
nkf.c
|
||||
nkf1.7/nkf.c
|
||||
test.rb
|
|
@ -0,0 +1 @@
|
|||
nkf.o : nkf.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h nkf1.7/nkf.c
|
|
@ -0,0 +1,2 @@
|
|||
require 'mkmf'
|
||||
create_makefile('nkf')
|
|
@ -0,0 +1,58 @@
|
|||
require 'nkf'
|
||||
|
||||
module Kconv
|
||||
AUTO = NKF::AUTO
|
||||
JIS = NKF::JIS
|
||||
EUC = NKF::EUC
|
||||
SJIS = NKF::SJIS
|
||||
BINARY = NKF::BINARY
|
||||
NOCONV = NKF::NOCONV
|
||||
UNKNOWN = NKF::UNKNOWN
|
||||
def kconv(str, out_code, in_code = AUTO)
|
||||
opt = '-'
|
||||
case in_code
|
||||
when NKF::JIS
|
||||
opt << 'J'
|
||||
when NKF::EUC
|
||||
opt << 'E'
|
||||
when NKF::SJIS
|
||||
opt << 'S'
|
||||
end
|
||||
|
||||
case out_code
|
||||
when NKF::JIS
|
||||
opt << 'j'
|
||||
when NKF::EUC
|
||||
opt << 'e'
|
||||
when NKF::SJIS
|
||||
opt << 's'
|
||||
when NKF::NOCONV
|
||||
return str
|
||||
end
|
||||
|
||||
opt = '' if opt == '-'
|
||||
|
||||
NKF::nkf(opt, str)
|
||||
end
|
||||
module_function :kconv
|
||||
|
||||
def tojis(str)
|
||||
NKF::nkf('-j', str)
|
||||
end
|
||||
module_function :tojis
|
||||
|
||||
def toeuc(str)
|
||||
NKF::nkf('-e', str)
|
||||
end
|
||||
module_function :toeuc
|
||||
|
||||
def tosjis(str)
|
||||
NKF::nkf('-s', str)
|
||||
end
|
||||
module_function :tosjis
|
||||
|
||||
def guess(str)
|
||||
NKF::guess(str)
|
||||
end
|
||||
module_function :guess
|
||||
end
|
|
@ -0,0 +1,206 @@
|
|||
#include "ruby.h"
|
||||
|
||||
#define _AUTO 0
|
||||
#define _JIS 1
|
||||
#define _EUC 2
|
||||
#define _SJIS 3
|
||||
#define _BINARY 4
|
||||
#define _NOCONV 4
|
||||
#define _UNKNOWN _AUTO
|
||||
|
||||
#undef getc
|
||||
#undef ungetc
|
||||
#define getc(f) (input_ctr>i_len?-1:input[input_ctr++])
|
||||
#define ungetc(c,f) input_ctr--
|
||||
|
||||
#undef putchar
|
||||
#define putchar(c) rb_nkf_putchar(c)
|
||||
|
||||
#define INCSIZE 32
|
||||
static int incsize;
|
||||
|
||||
static unsigned char *input, *output;
|
||||
static int input_ctr, i_len;
|
||||
static int output_ctr, o_len;
|
||||
|
||||
static VALUE dst;
|
||||
|
||||
static int
|
||||
rb_nkf_putchar(c)
|
||||
unsigned int c;
|
||||
{
|
||||
if (output_ctr >= o_len) {
|
||||
o_len += incsize;
|
||||
rb_str_cat(dst, "", incsize);
|
||||
incsize *= 2;
|
||||
}
|
||||
|
||||
output[output_ctr++] = c;
|
||||
/*
|
||||
printf("[[%c][%c][%d]]\n", c, output[output_ctr - 1], output_ctr);
|
||||
*/
|
||||
return c;
|
||||
}
|
||||
|
||||
#define PERL_XS 1
|
||||
#include "nkf1.7/nkf.c"
|
||||
|
||||
static VALUE
|
||||
rb_nkf_kconv(obj, opt, src)
|
||||
VALUE obj, opt, src;
|
||||
{
|
||||
int i;
|
||||
char *opt_ptr, *opt_end;
|
||||
|
||||
reinit();
|
||||
opt_ptr = str2cstr(opt, &i);
|
||||
opt_end = opt_ptr + i;
|
||||
for (; opt_ptr < opt_end; opt_ptr++) {
|
||||
if (*opt_ptr != '-') {
|
||||
continue;
|
||||
}
|
||||
arguments(opt_ptr);
|
||||
}
|
||||
|
||||
incsize = INCSIZE;
|
||||
|
||||
input_ctr = 0;
|
||||
input = str2cstr(src, &i_len);
|
||||
dst = rb_str_new(0, i_len*3 + 10); /* large enough? */
|
||||
|
||||
output_ctr = 0;
|
||||
output = RSTRING(dst)->ptr;
|
||||
o_len = RSTRING(dst)->len;
|
||||
*output = '\0';
|
||||
|
||||
if(iso8859_f && (oconv != j_oconv || !x0201_f )) {
|
||||
iso8859_f = FALSE;
|
||||
}
|
||||
|
||||
kanji_convert(NULL);
|
||||
if (output_ctr > 0) output_ctr--;
|
||||
if (output[output_ctr] == '\0') {
|
||||
/*
|
||||
printf("([%c][%d])\n", output[output_ctr], output_ctr);
|
||||
*/
|
||||
RSTRING(dst)->len = output_ctr;
|
||||
} else {
|
||||
/*
|
||||
printf("<[%c][%d]>\n", output[output_ctr], output_ctr);
|
||||
*/
|
||||
RSTRING(dst)->len = output_ctr + 1;
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
/*
|
||||
* Character code detection - Algorithm described in:
|
||||
* Ken Lunde. `Understanding Japanese Information Processing'
|
||||
* Sebastopol, CA: O'Reilly & Associates.
|
||||
*/
|
||||
|
||||
static VALUE
|
||||
rb_nkf_guess(obj, src)
|
||||
VALUE obj, src;
|
||||
{
|
||||
unsigned char *p;
|
||||
unsigned char *pend;
|
||||
int plen;
|
||||
int sequence_counter = 0;
|
||||
|
||||
Check_Type(src, T_STRING);
|
||||
|
||||
p = str2cstr(src, &plen);
|
||||
pend = p + plen;
|
||||
|
||||
#define INCR do {\
|
||||
p++;\
|
||||
if (p==pend) return INT2FIX(_UNKNOWN);\
|
||||
sequence_counter++;\
|
||||
if (sequence_counter % 2 == 1 && *p != 0xa4)\
|
||||
sequence_counter = 0;\
|
||||
if (6 <= sequence_counter) {\
|
||||
sequence_counter = 0;\
|
||||
return INT2FIX(_EUC);\
|
||||
}\
|
||||
} while (0)
|
||||
|
||||
if (*p == 0xa4)
|
||||
sequence_counter = 1;
|
||||
|
||||
while (p<pend) {
|
||||
if (*p == '\033') {
|
||||
return INT2FIX(_JIS);
|
||||
}
|
||||
if (*p < '\006' || *p == 0x7f || *p == 0xff) {
|
||||
return INT2FIX(_BINARY);
|
||||
}
|
||||
if (0x81 <= *p && *p <= 0x8d) {
|
||||
return INT2FIX(_SJIS);
|
||||
}
|
||||
if (0x8f <= *p && *p <= 0x9f) {
|
||||
return INT2FIX(_SJIS);
|
||||
}
|
||||
if (*p == 0x8e) { /* SS2 */
|
||||
INCR;
|
||||
if ((0x40 <= *p && *p <= 0x7e) ||
|
||||
(0x80 <= *p && *p <= 0xa0) ||
|
||||
(0xe0 <= *p && *p <= 0xfc))
|
||||
return INT2FIX(_SJIS);
|
||||
}
|
||||
else if (0xa1 <= *p && *p <= 0xdf) {
|
||||
INCR;
|
||||
if (0xf0 <= *p && *p <= 0xfe)
|
||||
return INT2FIX(_EUC);
|
||||
if (0xe0 <= *p && *p <= 0xef) {
|
||||
while (p < pend && *p >= 0x40) {
|
||||
if (*p >= 0x81) {
|
||||
if (*p <= 0x8d || (0x8f <= *p && *p <= 0x9f)) {
|
||||
return INT2FIX(_SJIS);
|
||||
}
|
||||
else if (0xfd <= *p && *p <= 0xfe) {
|
||||
return INT2FIX(_EUC);
|
||||
}
|
||||
}
|
||||
INCR;
|
||||
}
|
||||
}
|
||||
else if (*p <= 0x9f) {
|
||||
return INT2FIX(_SJIS);
|
||||
}
|
||||
}
|
||||
else if (0xf0 <= *p && *p <= 0xfe) {
|
||||
return INT2FIX(_EUC);
|
||||
}
|
||||
else if (0xe0 <= *p && *p <= 0xef) {
|
||||
INCR;
|
||||
if ((0x40 <= *p && *p <= 0x7e) ||
|
||||
(0x80 <= *p && *p <= 0xa0)) {
|
||||
return INT2FIX(_SJIS);
|
||||
}
|
||||
if (0xfd <= *p && *p <= 0xfe) {
|
||||
return INT2FIX(_EUC);
|
||||
}
|
||||
}
|
||||
INCR;
|
||||
}
|
||||
return INT2FIX(_UNKNOWN);
|
||||
}
|
||||
|
||||
void
|
||||
Init_nkf()
|
||||
{
|
||||
VALUE mKconv = rb_define_module("NKF");
|
||||
|
||||
rb_define_module_function(mKconv, "nkf", rb_nkf_kconv, 2);
|
||||
rb_define_module_function(mKconv, "guess", rb_nkf_guess, 1);
|
||||
|
||||
rb_define_const(mKconv, "AUTO", INT2FIX(_AUTO));
|
||||
rb_define_const(mKconv, "JIS", INT2FIX(_JIS));
|
||||
rb_define_const(mKconv, "EUC", INT2FIX(_EUC));
|
||||
rb_define_const(mKconv, "SJIS", INT2FIX(_SJIS));
|
||||
rb_define_const(mKconv, "BINARY", INT2FIX(_BINARY));
|
||||
rb_define_const(mKconv, "NOCONV", INT2FIX(_NOCONV));
|
||||
rb_define_const(mKconv, "UNKNOWN", INT2FIX(_UNKNOWN));
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,318 @@
|
|||
$counter = 0
|
||||
def result(result, message = nil)
|
||||
$counter += 1
|
||||
printf("%s %d%s\n",
|
||||
result ? 'ok' : 'no',
|
||||
$counter,
|
||||
message ? ' ... ' + message : '')
|
||||
end
|
||||
|
||||
begin
|
||||
require 'nkf'
|
||||
include NKF
|
||||
rescue LoadError
|
||||
result(false)
|
||||
end
|
||||
result(true)
|
||||
|
||||
if nkf('-me', '1')
|
||||
result(true);
|
||||
else
|
||||
result(false);
|
||||
end
|
||||
|
||||
output = nkf('-e', "\033\$@#1#3#2%B")
|
||||
if output
|
||||
# print output, "\n"
|
||||
result(true, output)
|
||||
else
|
||||
result(false)
|
||||
end
|
||||
|
||||
output = nkf('-Zj', "\033\$@#1#3#2%B")
|
||||
if output
|
||||
# print output, "\n"
|
||||
result(true, output)
|
||||
else
|
||||
result(false)
|
||||
end
|
||||
|
||||
output = "\244\306 " * 1024
|
||||
old = output.length
|
||||
output = nkf("-j", output)
|
||||
if output
|
||||
# print output, "\n"
|
||||
result(true, "#{old} #{output.length}")
|
||||
else
|
||||
result(false)
|
||||
end
|
||||
|
||||
|
||||
$detail = false
|
||||
def test(opt, input, expect)
|
||||
print "\nINPUT:\n", input if $detail
|
||||
print "\nEXPECT:\n", expect if $detail
|
||||
result = nkf(opt, input)
|
||||
print "\nGOT:\n", result if $detail
|
||||
|
||||
print result == expect ? "Ok\n" : "Fail\n"
|
||||
return result
|
||||
end
|
||||
|
||||
# Basic Conversion
|
||||
print "\nBasic Conversion test\n\n"
|
||||
|
||||
example = {}
|
||||
example['jis'] = <<'eofeof'.unpack('u')[0]
|
||||
M1FER<W0@4W1A9V4@&R1"(3DQ(3%^2R%+?D]3&RA"(%-E8V]N9"!3=&%G92`;
|
||||
M)$)0)TU:&RA"($AI<F%G86YA(!LD0B0B)"0D)B0H)"HD;R1R)',;*$(*2V%T
|
||||
M86MA;F$@&R1")2(E)"4F)2@E*B5O)7(E<QLH0B!+:6=O=2`;)$(A)B%G(S`C
|
||||
/029!)E@G(B=!*$`;*$(*
|
||||
eofeof
|
||||
#'
|
||||
|
||||
example['sjis'] = <<'eofeof'.unpack('u')[0]
|
||||
M1FER<W0@4W1A9V4@@5B)0(F>ED"6GIAR(%-E8V]N9"!3=&%G92"8I9=Y($AI
|
||||
M<F%G86YA((*@@J*"I(*F@JB"[8+P@O$*2V%T86MA;F$@@T�X-%@T>#28./
|
||||
>@Y*#DR!+:6=O=2"!18&'@D^"8(._@]:$081@A+X*
|
||||
eofeof
|
||||
#'
|
||||
|
||||
example['euc'] = <<'eofeof'.unpack('u')[0]
|
||||
M1FER<W0@4W1A9V4@H;FQH;'^RZ'+_L_3(%-E8V]N9"!3=&%G92#0I\W:($AI
|
||||
M<F%G86YA(*2BI*2DIJ2HI*JD[Z3RI/,*2V%T86MA;F$@I:*EI*6FI:BEJJ7O
|
||||
>I?*E\R!+:6=O=2"AIJ'GH["CP:;!IMBGHJ?!J,`*
|
||||
eofeof
|
||||
#'
|
||||
|
||||
example['amb'] = <<'eofeof'.unpack('u')[0]
|
||||
MI<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<*PL:7"L+&E
|
||||
MPK"QI<*PL:7"L+&EPK"QI<(*I<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<*P
|
||||
ML:7"L+&EPK"QI<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<(*I<*PL:7"L+&E
|
||||
MPK"QI<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<*PL:7"
|
||||
ML+&EPK"QI<(*I<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"Q
|
||||
MI<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<(*I<*PL:7"L+&EPK"QI<*PL:7"
|
||||
ML+&EPK"QI<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<(*
|
||||
eofeof
|
||||
|
||||
example['amb.euc'] = <<'eofeof'.unpack('u')[0]
|
||||
M&R1")4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25"
|
||||
M,#$E0C`Q)4(P,25",#$E0C`Q)4(;*$(*&R1")4(P,25",#$E0C`Q)4(P,25"
|
||||
M,#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(;
|
||||
M*$(*&R1")4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P
|
||||
M,25",#$E0C`Q)4(P,25",#$E0C`Q)4(;*$(*&R1")4(P,25",#$E0C`Q)4(P
|
||||
M,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q
|
||||
M)4(;*$(*&R1")4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q
|
||||
>)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(;*$(*
|
||||
eofeof
|
||||
|
||||
example['amb.sjis'] = <<'eofeof'.unpack('u')[0]
|
||||
M&RA))4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25"
|
||||
M,#$E0C`Q)4(P,25",#$E0C`Q)4(;*$(*&RA))4(P,25",#$E0C`Q)4(P,25"
|
||||
M,#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(;
|
||||
M*$(*&RA))4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P
|
||||
M,25",#$E0C`Q)4(P,25",#$E0C`Q)4(;*$(*&RA))4(P,25",#$E0C`Q)4(P
|
||||
M,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q
|
||||
M)4(;*$(*&RA))4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q
|
||||
>)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(;*$(*
|
||||
eofeof
|
||||
|
||||
example['x0201.sjis'] = <<'eofeof'.unpack('u')[0]
|
||||
MD5.*<(-*@TR#3H-0@U*#2X--@T^#48-3"I%3B7""8()A@F*"8X)D@F6"9H*!
|
||||
M@H*"@X*$@H6"AH*'"I%3BTR-AH%)@9>!E(&0@9.!3X&5@9:!:8%J@7R!>X&!
|
||||
M@6V!;H%O@7"!CPJ4O(IPMK>X/;FZMMZWWKC>N=ZZWH+&"I2\BG#*W\O?S-_-
|
||||
MW\[?M]^QW@K*W\O?S`IH86YK86MU(,K?R]_,I`K*W\O?S-VA"I2\BG""S(SC
|
||||
!"@!"
|
||||
eofeof
|
||||
#'
|
||||
|
||||
example['x0201.euc'] = <<'eofeof'.unpack('u')[0]
|
||||
MP;2ST:6KI:VEKZ6QI;.EK*6NI;"ELJ6T"L&TL=&CP:/"H\.CQ*/%H\:CQZ/A
|
||||
MH^*CXZ/DH^6CYJ/G"L&TM:VYYJ&JH?>A]*'PH?.AL*'UH?:ARJ'+H=VAW*'A
|
||||
MH<ZASZ'0H=&A[PK(OK/1CK:.MXZX/8ZYCKJ.MH[>CK>.WHZXCMZ.N8[>CKJ.
|
||||
MWJ3("LB^L]&.RH[?CLN.WX[,CM^.S8[?CLZ.WXZWCM^.L8[>"H[*CM^.RX[?
|
||||
MCLP*:&%N:V%K=2".RH[?CLN.WX[,CJ0*CLJ.WX[+CM^.S([=CJ$*R+ZST:3.
|
||||
#N.4*
|
||||
eofeof
|
||||
#'
|
||||
|
||||
example['x0201.jis'] = <<'eofeof'.unpack('u')[0]
|
||||
M&R1"030S424K)2TE+R4Q)3,E+"4N)3`E,B4T&RA""ALD0D$T,5$C02-"(T,C
|
||||
M1"-%(T8C1R-A(V(C8R-D(V4C9B-G&RA""ALD0D$T-2TY9B$J(7<A="%P(7,A
|
||||
M,"%U(78A2B%+(5TA7"%A(4XA3R%0(5$A;QLH0@H;)$)(/C-1&RA)-C<X&RA"
|
||||
M/1LH23DZ-EXW7CA>.5XZ7ALD0B1(&RA""ALD0D@^,U$;*$E*7TM?3%]-7TY?
|
||||
M-U\Q7ALH0@H;*$E*7TM?3!LH0@IH86YK86MU(!LH24I?2U],)!LH0@H;*$E*
|
||||
97TM?3%TA&RA""ALD0D@^,U$D3CAE&RA""@``
|
||||
eofeof
|
||||
#`
|
||||
|
||||
example['x0201.sosi'] = <<'eofeof'.unpack('u')[0]
|
||||
M&R1"030S424K)2TE+R4Q)3,E+"4N)3`E,B4T&RA*"ALD0D$T,5$C02-"(T,C
|
||||
M1"-%(T8C1R-A(V(C8R-D(V4C9B-G&RA*"ALD0D$T-2TY9B$J(7<A="%P(7,A
|
||||
M,"%U(78A2B%+(5TA7"%A(4XA3R%0(5$A;QLH2@H;)$)(/C-1&RA*#C8W.`\;
|
||||
M*$H]#CDZ-EXW7CA>.5XZ7@\;)$(D2!LH2@H;)$)(/C-1&RA*#DI?2U],7TU?
|
||||
M3E\W7S%>#PH.2E]+7TP/&RA*"FAA;FMA:W4@#DI?2U],)`\;*$H*#DI?2U],
|
||||
672$/&RA*"ALD0D@^,U$D3CAE&RA""@``
|
||||
eofeof
|
||||
#"
|
||||
|
||||
example['x0201.x0208'] = <<'eofeof'.unpack('u')[0]
|
||||
M&R1"030S424K)2TE+R4Q)3,E+"4N)3`E,B4T&RA""ALD0D$T,5$;*$)!0D-$
|
||||
M149'86)C9&5F9PH;)$)!-#4M.68;*$(A0",D)5XF*B@I+2L]6UU[?1LD0B%O
|
||||
M&RA""ALD0D@^,U$E*R4M)2\;*$(]&R1")3$E,R4L)2XE,"4R)30D2!LH0@H;
|
||||
M)$)(/C-1)5$E5"57)5HE724M(2PE(B$K&RA""ALD0B51)50E51LH0@IH86YK
|
||||
M86MU(!LD0B51)50E52$B&RA""ALD0B51)50E525S(2,;*$(*&R1"2#XS421.
|
||||
&.&4;*$(*
|
||||
eofeof
|
||||
#`
|
||||
|
||||
example['mime.iso2022'] = <<'eofeof'.unpack('u')[0]
|
||||
M/3])4T\M,C`R,BU*4#]"/T=Y4D%.144W96E23TI566Q/4U9)1WEH2S\]"CT_
|
||||
M:7-O+3(P,C(M2E`_0C]'>5)!3D5%-V5I4D]*55EL3U-624=Y:$L_/0H]/VES
|
||||
M;RTR,#(R+4I0/U$_/3%")$(D1B11/3%"*$)?96YD/ST*&R1`)#TD)B0K)$H;
|
||||
M*$H@/3])4T\M,C`R,BU*4#]"/T=Y4D%.144W96E23U!Y:S=D:'-O4V<]/3\]
|
||||
M(&5N9"!O9B!L:6YE"CT_25-/+3(P,C(M2E`_0C]'>5)!3D5%-V5I4D]0>6LW
|
||||
M9&AS;U-G/3T_/2`]/TE33RTR,#(R+4I0/T(_1WE204Y%13=E:5)/4'EK-V1H
|
||||
M<V]39ST]/ST*0G)O:V5N(&-A<V4*/3])4T\M,C`R,BU*4#]"/T=Y4D%.144W
|
||||
M96E23U!Y:S=D"FAS;U-G/3T_/2`]/TE33RTR,`HR,BU*4#]"/T=Y4D%.144W
|
||||
M96E23U!Y:S=D:'-O4V<]/3\]"CT_25-/+3(P,C(M2E`_0C]'>5)!3D5%-V5I
|
||||
44D]*55EL3QM;2U-624=Y:$L_/0H_
|
||||
eofeof
|
||||
#'
|
||||
|
||||
example['mime.ans.strict'] = <<'eofeof'.unpack('u')[0]
|
||||
M&R1"-$$[>B1.)48E.25(&RA""ALD0C1!.WHD3B5&)3DE2!LH0@H;)$(D1B11
|
||||
M&RA"(&5N9`H;)$(D/20F)"LD2ALH0B`;)$(T03MZ)$X_*3MV&RA"96YD(&]F
|
||||
M(&QI;F4*&R1"-$$[>B1./RD[=C1!.WHD3C\I.W8;*$(*0G)O:V5N(&-A<V4*
|
||||
M/3])4T\M,C`R,BU*4#]"/T=Y4D%.144W96E23U!Y:S=D"FAS;U-G/3T_/2`]
|
||||
M/TE33RTR,`HR,BU*4#]"/T=Y4D%.144W96E23U!Y:S=D:'-O4V<]/3\]"CT_
|
||||
L25-/+3(P,C(M2E`_0C]'>5)!3D5%-V5I4D]*55EL3QM;2U-624=Y:$L_/0H_
|
||||
eofeof
|
||||
#'
|
||||
|
||||
example['mime.unbuf.strict'] = <<'eofeof'.unpack('u')[0]
|
||||
M&R1"-$$[>B1.)48E.25(&RA""ALD0C1!.WHD3B5&)3DE2!LH0@H;)$(D1B11
|
||||
M&RA"(&5N9`H;)$(D/20F)"LD2ALH0B`;)$(T03MZ)$X_*3MV&RA"96YD(&]F
|
||||
M(&QI;F4*&R1"-$$[>B1./RD[=C1!.WHD3C\I.W8;*$(*0G)O:V5N(&-A<V4*
|
||||
M&R1"-$$[>B1./RD;*$)H<V]39ST]/ST@/3])4T\M,C`*,C(M2E`_0C]'>5)!
|
||||
M3D5%-V5I4D]0>6LW9&AS;U-G/3T_/0H;)$(T03MZ)$XE1ALH0EM+4U9)1WEH
|
||||
$2S\]"F5I
|
||||
eofeof
|
||||
|
||||
example['mime.ans'] = <<'eofeof'.unpack('u')[0]
|
||||
M&R1"-$$[>B1.)48E.25(&RA""ALD0C1!.WHD3B5&)3DE2!LH0@H;)$(D1B11
|
||||
M&RA"(&5N9`H;)$(D/20F)"LD2ALH0B`;)$(T03MZ)$X_*3MV&RA"96YD(&]F
|
||||
M(&QI;F4*&R1"-$$[>B1./RD[=C1!.WHD3C\I.W8;*$(*0G)O:V5N(&-A<V4*
|
||||
M&R1"-$$[>B1./RD;*$)H<V]39ST]/ST@&R1"-$$[>B1./RD[=ALH0@H;)$(T
|
||||
603MZ)$XE1ALH0EM+4U9)1WEH2S\]"@`*
|
||||
eofeof
|
||||
#"
|
||||
|
||||
example['mime.unbuf'] = <<'eofeof'.unpack('u')[0]
|
||||
M&R1"-$$[>B1.)48E.25(&RA""ALD0C1!.WHD3B5&)3DE2!LH0@H;)$(D1B11
|
||||
M&RA"(&5N9`H;)$(D/20F)"LD2ALH0B`;)$(T03MZ)$X_*3MV&RA"96YD(&]F
|
||||
M(&QI;F4*&R1"-$$[>B1./RD[=C1!.WHD3C\I.W8;*$(*0G)O:V5N(&-A<V4*
|
||||
M&R1"-$$[>B1./RD;*$)H<V]39ST]/ST@&R1"-$$[>B1./RD[=ALH0@H;)$(T
|
||||
603MZ)$XE1ALH0EM+4U9)1WEH2S\]"@`*
|
||||
eofeof
|
||||
#"
|
||||
|
||||
example['mime.base64'] = <<'eofeof'.unpack('u')[0]
|
||||
M9W-M5"])3&YG<FU#>$I+-&=Q=4,S24LS9W%Q0E%:3TUI-39,,S0Q-&=S5T)1
|
||||
M43!+9VUA1%9O3T@*9S)+1%1O3'=K8C)1;$E+;V=Q2T-X24MG9W5M0W%*3EEG
|
||||
<<T=#>$E+9V=U;4,X64Q&9W)70S592VMG<6U""F=Q
|
||||
eofeof
|
||||
#"
|
||||
|
||||
example['mime.base64.ans'] = <<'eofeof'.unpack('u')[0]
|
||||
M&R1")$M&?B1I)#LD1D0Z)"TD7B0Y)"PA(D5L-7XV83E9)$<A(ALH0@T*&R1"
|
||||
M(T<E-R5G)4,E+R1R0C\_="0J)"0D1B0B)&LD*D4Y)$,D1B0B)&LD<R1')#<D
|
||||
(9R0F)"L;*$(E
|
||||
eofeof
|
||||
#'
|
||||
|
||||
example['mime.is8859'] = <<'eofeof'.unpack('u')[0]
|
||||
M/3])4T\M.#@U.2TQ/U$_*CU#-V%V83\_/2`*4&5E<B!4]G)N9W)E;@I,87-S
|
||||
M92!(:6QL97+X92!0971E<G-E;B`@7"`B36EN(&MA97!H97-T(&AA<B!F86%E
|
||||
M="!E="!F;V5L(2(*06%R:'5S(%5N:79E<G-I='DL($1%3DU!4DL@(%P@(DUI
|
||||
<;B!KYG!H97-T(&AA<B!FY65T(&5T(&;X;"$B"@!K
|
||||
eofeof
|
||||
|
||||
example['mime.is8859.ans'] = <<'eofeof'.unpack('u')[0]
|
||||
M*L=A=F$_(`I0965R(%3V<FYG<F5N"DQA<W-E($AI;&QE<OAE(%!E=&5R<V5N
|
||||
M("!<(")-:6X@:V%E<&AE<W0@:&%R(&9A865T(&5T(&9O96PA(@I!87)H=7,@
|
||||
M56YI=F5R<VET>2P@1$5.34%22R`@7"`B36EN(&OF<&AE<W0@:&%R(&;E970@
|
||||
)970@9OAL(2(*
|
||||
eofeof
|
||||
#"
|
||||
|
||||
print 'JIS to JIS ... '; test(' ', example['jis'], example['jis'])
|
||||
print 'JIS to SJIS... '; test('-s', example['jis'], example['sjis'])
|
||||
print 'JIS to EUC ... '; test('-e', example['jis'], example['euc'])
|
||||
|
||||
print 'SJIS to JIS ... '; test('-j', example['sjis'], example['jis'])
|
||||
print 'SJIS to SJIS... '; test('-s', example['sjis'], example['sjis'])
|
||||
print 'SJIS to EUC ... '; test('-e', example['sjis'], example['euc'])
|
||||
|
||||
print 'EUC to JIS ... '; test(' ', example['euc'], example['jis'])
|
||||
print 'EUC to SJIS... '; test('-s', example['euc'], example['sjis'])
|
||||
print 'EUC to EUC ... '; test('-e', example['euc'], example['euc'])
|
||||
|
||||
|
||||
# Ambigous Case
|
||||
print 'Ambiguous Case. '; test('' , example['amb'], example['amb.euc'])
|
||||
|
||||
# Input assumption
|
||||
print 'SJIS Input assumption '
|
||||
test('-Sx', example['amb'], example['amb.sjis'])
|
||||
|
||||
# X0201 ²¾Ì¾
|
||||
# X0201->X0208 conversion
|
||||
# X0208 aphabet -> ASCII
|
||||
# X0201 Áê¸ßÊÑ´¹
|
||||
|
||||
print "\nX0201 test\n\n"
|
||||
|
||||
# -X is necessary to allow X0201 in SJIS
|
||||
# -Z convert X0208 alphabet to ASCII
|
||||
print 'X0201 conversion: SJIS '
|
||||
test('-XZ', example['x0201.sjis'], example['x0201.x0208'])
|
||||
print 'X0201 conversion: JIS '
|
||||
test('-Z', example['x0201.jis'], example['x0201.x0208'])
|
||||
print 'X0201 conversion:SI/SO '
|
||||
test('-Z', example['x0201.sosi'], example['x0201.x0208'])
|
||||
print 'X0201 conversion: EUC '
|
||||
test('-Z', example['x0201.euc'], example['x0201.x0208'])
|
||||
# -x means X0201 output
|
||||
print 'X0201 output: SJIS '
|
||||
test('-xs', example['x0201.euc'], example['x0201.sjis'])
|
||||
print 'X0201 output: JIS '
|
||||
test('-xj', example['x0201.sjis'], example['x0201.jis'])
|
||||
print 'X0201 output: EUC '
|
||||
test('-xe', example['x0201.jis'], example['x0201.euc'])
|
||||
|
||||
# MIME decode
|
||||
|
||||
print "\nMIME test\n\n"
|
||||
|
||||
# MIME ISO-2022-JP
|
||||
|
||||
print "Next test is expeced to Fail.\n"
|
||||
|
||||
print 'MIME decode (strict) '
|
||||
tmp = test('-m', example['mime.iso2022'], example['mime.ans.strict'])
|
||||
print 'MIME decode (nonstrict)'
|
||||
tmp = test('-m', example['mime.iso2022'], example['mime.ans'])
|
||||
# open(OUT,'>tmp1');print OUT pack('u',$tmp);close(OUT);
|
||||
# unbuf mode implies more pessimistic decode
|
||||
print 'MIME decode (unbuf) '
|
||||
test('-mu', example['mime.iso2022'], example['mime.unbuf'])
|
||||
print 'MIME decode (base64) '
|
||||
t = test('-mB', example['mime.base64'], example['mime.base64.ans'])
|
||||
|
||||
# MIME ISO-8859-1
|
||||
|
||||
# Without -l, ISO-8859-1 was handled as X0201.
|
||||
|
||||
print 'MIME ISO-8859-1 (Q) '
|
||||
test('-ml', example['mime.is8859'], example['mime.is8859.ans'])
|
|
@ -0,0 +1,11 @@
|
|||
MANIFEST
|
||||
README
|
||||
README.expect
|
||||
README.expect.jp
|
||||
README.jp
|
||||
expect_sample.rb
|
||||
extconf.rb
|
||||
lib/expect.rb
|
||||
pty.c
|
||||
script.rb
|
||||
shl.rb
|
|
@ -0,0 +1,93 @@
|
|||
pty extension version 0.3 by A.ito
|
||||
|
||||
1. Introduction
|
||||
|
||||
This extension module adds ruby a functionality to execute an
|
||||
arbitrary command through pseudo tty (pty).
|
||||
|
||||
2. Install
|
||||
|
||||
Follow the instruction below.
|
||||
|
||||
(1) Execute
|
||||
|
||||
ruby extconf.rb
|
||||
|
||||
then Makefile is generated.
|
||||
|
||||
(3) Do make; make install.
|
||||
|
||||
3. What you can do
|
||||
|
||||
This extension module defines a module named PTY, which contains
|
||||
following module fungtions:
|
||||
|
||||
getpty(command)
|
||||
spawn(command)
|
||||
|
||||
This function reserves a pty, executes command over the pty
|
||||
and returns an array. The return value is an array with three
|
||||
elements. The first element in the array is for reading and the
|
||||
second for writing. The third element is the process ID of the
|
||||
child process. If this function is called with an iterator block,
|
||||
the array is passed to the block as block parameters, and the
|
||||
function itself returns nil.
|
||||
|
||||
While the process spawned by this function is active, SIGCHLD
|
||||
is captured to handle the change of the child process. When the
|
||||
child process is suspended or finished, an exception is raised.
|
||||
As all SIGCHLD signal is captured and processed by PTY module,
|
||||
you can't use other function or method which spawns subprosesses
|
||||
(including signal() and IO.popen()) while the PTY subprocesses
|
||||
are active. Otherwise, unexpected exception will occur. To avoid
|
||||
this problem, see protect_signal() below.
|
||||
|
||||
If this function is called with an iterator block, SIGCHLD signal
|
||||
is captured only within the block. Therefore, it is risky to use
|
||||
File objects for PTY subprocess outside the iterator block.
|
||||
|
||||
|
||||
protect_signal
|
||||
|
||||
This function takes an iterator block. Within the iterator block,
|
||||
no exception is raised even if any subprocess is terminated.
|
||||
This function is used to enable functions like system() or IO.popen()
|
||||
while PTY subprocess is active. For example,
|
||||
|
||||
PTY.spawn("command_foo") do |r,w|
|
||||
...
|
||||
...
|
||||
PTY.protect_signal do
|
||||
system "some other commands"
|
||||
end
|
||||
...
|
||||
end
|
||||
|
||||
disables to send exception when "some other commands" is
|
||||
terminated.
|
||||
|
||||
reset_signal
|
||||
|
||||
Disables to handle SIGCHLD while PTY subprocess is active.
|
||||
|
||||
|
||||
4. License
|
||||
|
||||
(C) Copyright 1998 by Akinori Ito.
|
||||
|
||||
This software may be redistributed freely for this purpose, in full
|
||||
or in part, provided that this entire copyright notice is included
|
||||
on any copies of this software and applications and derivations thereof.
|
||||
|
||||
This software is provided on an "as is" basis, without warranty of any
|
||||
kind, either expressed or implied, as to any matter including, but not
|
||||
limited to warranty of fitness of purpose, or merchantability, or
|
||||
results obtained from use of this software.
|
||||
|
||||
5. Bug report
|
||||
|
||||
Please feel free to send E-mail to
|
||||
|
||||
aito@ei5sun.yz.yamagata-u.ac.jp
|
||||
|
||||
for any bug report, opinion, contribution, etc.
|
|
@ -0,0 +1,22 @@
|
|||
README for expect
|
||||
by A. Ito, 28 October, 1998
|
||||
|
||||
Expect library adds IO class a method called expect(), which
|
||||
does similar act to tcl's expect extension.
|
||||
|
||||
The usage of the method is:
|
||||
|
||||
IO#expect(pattern,timeout=9999999)
|
||||
|
||||
where `pattern' is an instance of String or Regexp and `timeout'
|
||||
is Fixnum, which can be omitted.
|
||||
When the method is called without block, it waits until the
|
||||
input which matches the pattern is obtained from the IO or the time
|
||||
specified as the timeout passes. When the pattern is obtained from the
|
||||
IO, the method returns an array. The first element of the array is the
|
||||
entire string obtained from the IO until the pattern matches. The
|
||||
following elements indicates the specific pattern which matched to the
|
||||
anchor in the regular expression. If the method ends because of
|
||||
timeout, it returns nil.
|
||||
When the method is called with block, the array is passed as
|
||||
the block parameter.
|
|
@ -0,0 +1,21 @@
|
|||
README for expect
|
||||
by A. Ito, 28 October, 1998
|
||||
|
||||
Expectライブラリは,tcl の expect パッケージと似たような機能を
|
||||
IOクラスに追加します.
|
||||
|
||||
追加されるメソッドの使い方は次の通りです.
|
||||
|
||||
IO#expect(pattern,timeout=9999999)
|
||||
|
||||
pattern は String か Regexp のインスタンス,timeout は Fixnum
|
||||
のインスタンスです.timeout は省略できます.
|
||||
このメソッドがブロックなしで呼ばれた場合,まずレシーバである
|
||||
IOオブジェクトから pattern にマッチするパターンが読みこまれる
|
||||
まで待ちます.パターンが得られたら,そのパターンに関する配列を
|
||||
返します.配列の最初の要素は,pattern にマッチするまでに読みこ
|
||||
まれた内容の文字列です.2番目以降の要素は,pattern の正規表現
|
||||
の中にアンカーがあった場合に,そのアンカーにマッチする部分です.
|
||||
もしタイムアウトが起きた場合は,このメソッドはnilを返します.
|
||||
このメソッドがブロック付きで呼ばれた場合には,マッチした要素の
|
||||
配列がブロック引数として渡され,ブロックが評価されます.
|
|
@ -0,0 +1,89 @@
|
|||
pty 拡張モジュール version 0.3 by A.ito
|
||||
|
||||
1. はじめに
|
||||
|
||||
この拡張モジュールは,仮想tty (pty) を通して適当なコマンドを
|
||||
実行する機能を ruby に提供します.
|
||||
|
||||
2. インストール
|
||||
|
||||
次のようにしてインストールしてください.
|
||||
|
||||
(1) ruby extconf.rb
|
||||
|
||||
を実行すると Makefile が生成されます.
|
||||
|
||||
(2) make; make install を実行してください.
|
||||
|
||||
3. 何ができるか
|
||||
|
||||
この拡張モジュールは,PTY というモジュールを定義します.その中
|
||||
には,次のようなモジュール関数が含まれています.
|
||||
|
||||
getpty(command)
|
||||
spawn(command)
|
||||
|
||||
この関数は,仮想ttyを確保し,指定されたコマンドをその仮想tty
|
||||
の向こうで実行し,配列を返します.戻り値は3つの要素からなる
|
||||
配列です.最初の要素は仮想ttyから読み出すためのIOオブジェクト,
|
||||
2番目は書きこむためのIOオブジェクト,3番目は子プロセスのプロ
|
||||
セスIDです.この関数がイテレータとして呼ばれた場合,これらの
|
||||
要素はブロックパラメータとして渡され,関数自体はnilを返します.
|
||||
|
||||
この関数によって作られたサブプロセスが動いている間,子プロセス
|
||||
の状態を監視するために SIGCHLD シグナルを捕捉します.子プロセス
|
||||
が終了したり停止した場合には,例外が発生します.この間,すべての
|
||||
SIGCHLD が PTY モジュールのシグナルハンドラに捕捉されるので,
|
||||
サブプロセスを生成する他の関数(system() とか IO.popen()など)を
|
||||
使うと,予期しない例外が発生することがあります.これを防ぐため
|
||||
には,下記のprotect_signal()を参照してください.
|
||||
|
||||
この関数がブロックパラメータ付きで呼ばれた場合には,そのブロック
|
||||
の中でのみ SIGCHLD が捕捉されます.したがって,ブロックパラメータ
|
||||
として渡されたIOオブジェクトを,ブロックの外に持ち出して使うの
|
||||
は勧められません.
|
||||
|
||||
|
||||
protect_signal
|
||||
|
||||
この関数はイテレータです.ここで指定されたブロックの中では,
|
||||
子プロセスが終了しても例外を発生しません.この関数を使うことで,
|
||||
PTYの子プロセスが動いている間でも,system()や IO.popen()などの
|
||||
関数を安全に使うことができます.例えば,
|
||||
|
||||
PTY.spawn("command_foo") do |r,w|
|
||||
...
|
||||
...
|
||||
PTY.protect_signal do
|
||||
system "some other commands"
|
||||
end
|
||||
...
|
||||
end
|
||||
|
||||
このような記述により,"some other commands" が終了したときに
|
||||
例外が発生するのを防げます.
|
||||
|
||||
reset_signal
|
||||
|
||||
PTY の子プロセスが動いていても,そのプロセスの終了時に例外が発生
|
||||
しないようにします.
|
||||
|
||||
4. 利用について
|
||||
|
||||
伊藤彰則が著作権を保有します.
|
||||
|
||||
ソースプログラムまたはドキュメントに元の著作権表示が改変されずに
|
||||
表示されている場合に限り,誰でも,このソフトウェアを無償かつ著作
|
||||
権者に無断で利用・配布・改変できます.利用目的は限定されていませ
|
||||
ん.
|
||||
|
||||
このプログラムの利用・配布その他このプログラムに関係する行為によ
|
||||
って生じたいかなる損害に対しても,作者は一切責任を負いません.
|
||||
|
||||
5. バグ報告等
|
||||
|
||||
バグレポートは歓迎します.
|
||||
|
||||
aito@ei5sun.yz.yamagata-u.ac.jp
|
||||
|
||||
まで電子メールでバグレポートをお送りください.
|
|
@ -0,0 +1,56 @@
|
|||
#
|
||||
# sample program of expect.rb
|
||||
#
|
||||
# by A. Ito
|
||||
#
|
||||
# This program reports the latest version of ruby interpreter
|
||||
# by connecting to ftp server at netlab.co.jp.
|
||||
#
|
||||
require 'pty'
|
||||
require 'expect'
|
||||
|
||||
fnames = []
|
||||
PTY.spawn("ftp ftp.netlab.co.jp") do
|
||||
|r_f,w_f,pid|
|
||||
w_f.sync = true
|
||||
|
||||
$expect_verbose = true
|
||||
|
||||
r_f.expect(/^Name.*: /) do
|
||||
w_f.print "ftp\n"
|
||||
end
|
||||
|
||||
if !ENV['USER'].nil?
|
||||
username = ENV['USER']
|
||||
elsif !ENV['LOGNAME'].nil?
|
||||
username = ENV['LOGNAME']
|
||||
else
|
||||
username = 'guest'
|
||||
end
|
||||
|
||||
r_f.expect('word:') do
|
||||
w_f.print username+"@\n"
|
||||
end
|
||||
r_f.expect("ftp> ") do
|
||||
w_f.print "cd pub/lang/ruby\n"
|
||||
end
|
||||
r_f.expect("ftp> ") do
|
||||
w_f.print "dir\n"
|
||||
end
|
||||
|
||||
r_f.expect("ftp> ") do |output|
|
||||
for x in output[0].split("\n")
|
||||
if x =~ /(ruby.*\.tar\.gz)/ then
|
||||
fnames.push $1
|
||||
end
|
||||
end
|
||||
end
|
||||
begin
|
||||
w_f.print "quit\n"
|
||||
rescue
|
||||
end
|
||||
end
|
||||
|
||||
print "The latest ruby interpreter is "
|
||||
print fnames.sort.pop
|
||||
print "\n"
|
|
@ -0,0 +1,10 @@
|
|||
require 'mkmf'
|
||||
|
||||
have_header("sys/stropts.h")
|
||||
have_func("setresuid")
|
||||
$CFLAGS << "-DHAVE_DEV_PTMX" if /cygwin/ === PLATFORM
|
||||
if have_func("openpty") or
|
||||
have_func("_getpty") or
|
||||
have_func("ioctl")
|
||||
create_makefile('pty')
|
||||
end
|
|
@ -0,0 +1,36 @@
|
|||
$expect_verbose = false
|
||||
|
||||
class IO
|
||||
def expect(pat,timeout=9999999)
|
||||
buf = ''
|
||||
case pat
|
||||
when String
|
||||
e_pat = Regexp.new(Regexp.quote(pat))
|
||||
when Regexp
|
||||
e_pat = pat
|
||||
end
|
||||
while true
|
||||
if IO.select([self],nil,nil,timeout).nil? then
|
||||
result = nil
|
||||
break
|
||||
end
|
||||
c = getc.chr
|
||||
buf << c
|
||||
if $expect_verbose
|
||||
STDOUT.print c
|
||||
STDOUT.flush
|
||||
end
|
||||
if buf =~ e_pat then
|
||||
result = [buf,$1,$2,$3,$4,$5,$6,$7,$8,$9]
|
||||
break
|
||||
end
|
||||
end
|
||||
if iterator? then
|
||||
yield result
|
||||
else
|
||||
return result
|
||||
end
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,497 @@
|
|||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/file.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <pwd.h>
|
||||
#if !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_WAIT_H
|
||||
#include <sys/wait.h>
|
||||
#else
|
||||
#define WIFSTOPPED(status) (((status) & 0xff) == 0x7f)
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
|
||||
#include <ruby.h>
|
||||
#include <rubyio.h>
|
||||
|
||||
#include <signal.h>
|
||||
#ifdef HAVE_SYS_STROPTS_H
|
||||
#include <sys/stropts.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#define DEVICELEN 16
|
||||
|
||||
#if !defined(HAVE_OPENPTY)
|
||||
#ifdef __hpux
|
||||
char *MasterDevice = "/dev/ptym/pty%s",
|
||||
*SlaveDevice = "/dev/pty/tty%s",
|
||||
*deviceNo[] = {
|
||||
"p0","p1","p2","p3","p4","p5","p6","p7",
|
||||
"p8","p9","pa","pb","pc","pd","pe","pf",
|
||||
"q0","q1","q2","q3","q4","q5","q6","q7",
|
||||
"q8","q9","qa","qb","qc","qd","qe","qf",
|
||||
"r0","r1","r2","r3","r4","r5","r6","r7",
|
||||
"r8","r9","ra","rb","rc","rd","re","rf",
|
||||
"s0","s1","s2","s3","s4","s5","s6","s7",
|
||||
"s8","s9","sa","sb","sc","sd","se","sf",
|
||||
"t0","t1","t2","t3","t4","t5","t6","t7",
|
||||
"t8","t9","ta","tb","tc","td","te","tf",
|
||||
"u0","u1","u2","u3","u4","u5","u6","u7",
|
||||
"u8","u9","ua","ub","uc","ud","ue","uf",
|
||||
"v0","v1","v2","v3","v4","v5","v6","v7",
|
||||
"v8","v9","va","vb","vc","vd","ve","vf",
|
||||
"w0","w1","w2","w3","w4","w5","w6","w7",
|
||||
"w8","w9","wa","wb","wc","wd","we","wf",
|
||||
0,
|
||||
};
|
||||
#else /* NOT HPUX */
|
||||
#ifdef _IBMESA /* AIX/ESA */
|
||||
char *MasterDevice = "/dev/ptyp%s",
|
||||
*SlaveDevice = "/dev/ttyp%s",
|
||||
*deviceNo[] = {
|
||||
"00","01","02","03","04","05","06","07","08","09","0a","0b","0c","0d","0e","0f",
|
||||
"10","11","12","13","14","15","16","17","18","19","1a","1b","1c","1d","1e","1f",
|
||||
"20","21","22","23","24","25","26","27","28","29","2a","2b","2c","2d","2e","2f",
|
||||
"30","31","32","33","34","35","36","37","38","39","3a","3b","3c","3d","3e","3f",
|
||||
"40","41","42","43","44","45","46","47","48","49","4a","4b","4c","4d","4e","4f",
|
||||
"50","51","52","53","54","55","56","57","58","59","5a","5b","5c","5d","5e","5f",
|
||||
"60","61","62","63","64","65","66","67","68","69","6a","6b","6c","6d","6e","6f",
|
||||
"70","71","72","73","74","75","76","77","78","79","7a","7b","7c","7d","7e","7f",
|
||||
"80","81","82","83","84","85","86","87","88","89","8a","8b","8c","8d","8e","8f",
|
||||
"90","91","92","93","94","95","96","97","98","99","9a","9b","9c","9d","9e","9f",
|
||||
"a0","a1","a2","a3","a4","a5","a6","a7","a8","a9","aa","ab","ac","ad","ae","af",
|
||||
"b0","b1","b2","b3","b4","b5","b6","b7","b8","b9","ba","bb","bc","bd","be","bf",
|
||||
"c0","c1","c2","c3","c4","c5","c6","c7","c8","c9","ca","cb","cc","cd","ce","cf",
|
||||
"d0","d1","d2","d3","d4","d5","d6","d7","d8","d9","da","db","dc","dd","de","df",
|
||||
"e0","e1","e2","e3","e4","e5","e6","e7","e8","e9","ea","eb","ec","ed","ee","ef",
|
||||
"f0","f1","f2","f3","f4","f5","f6","f7","f8","f9","fa","fb","fc","fd","fe","ff",
|
||||
};
|
||||
#else
|
||||
char *MasterDevice = "/dev/pty%s",
|
||||
*SlaveDevice = "/dev/tty%s",
|
||||
*deviceNo[] = {
|
||||
"p0","p1","p2","p3","p4","p5","p6","p7",
|
||||
"p8","p9","pa","pb","pc","pd","pe","pf",
|
||||
"q0","q1","q2","q3","q4","q5","q6","q7",
|
||||
"q8","q9","qa","qb","qc","qd","qe","qf",
|
||||
"r0","r1","r2","r3","r4","r5","r6","r7",
|
||||
"r8","r9","ra","rb","rc","rd","re","rf",
|
||||
0,
|
||||
};
|
||||
#endif /* _IBMESA */
|
||||
#endif /* HPUX */
|
||||
#endif /* !defined(HAVE_OPENPTY) */
|
||||
|
||||
char SlaveName[DEVICELEN];
|
||||
|
||||
extern int errno;
|
||||
|
||||
#define MAX_PTY 16
|
||||
static int n_pty,last_pty;
|
||||
static int chld_pid[MAX_PTY];
|
||||
|
||||
#ifndef HAVE_SETEUID
|
||||
# ifdef HAVE_SETREUID
|
||||
# define seteuid(e) setreuid(-1, (e))
|
||||
# else /* NOT HAVE_SETREUID */
|
||||
# ifdef HAVE_SETRESUID
|
||||
# define seteuid(e) setresuid(-1, (e), -1)
|
||||
# else /* NOT HAVE_SETRESUID */
|
||||
/* I can't set euid. (;_;) */
|
||||
# endif /* HAVE_SETRESUID */
|
||||
# endif /* HAVE_SETREUID */
|
||||
#endif /* NO_SETEUID */
|
||||
|
||||
struct pty_info {
|
||||
int fd;
|
||||
pid_t child_pid;
|
||||
};
|
||||
|
||||
static void
|
||||
set_signal_action(action)
|
||||
RETSIGTYPE (*action)();
|
||||
{
|
||||
#ifdef __hpux
|
||||
struct sigvec sv;
|
||||
/*
|
||||
* signal SIGCHLD should be delivered on stop of the child
|
||||
*/
|
||||
sv.sv_handler = action;
|
||||
sv.sv_mask = sigmask(SIGCHLD);
|
||||
sv.sv_flags = SV_BSDSIG;
|
||||
sigvector(SIGCHLD, &sv, (struct sigvec *) 0);
|
||||
#else /* not HPUX */
|
||||
#if defined(SA_NOCLDSTOP)
|
||||
struct sigaction sa;
|
||||
/*
|
||||
* signal SIGCHLD should be delivered on stop of the child
|
||||
* (for SVR4)
|
||||
*/
|
||||
sa.sa_handler = action;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sigaddset(&sa.sa_mask, SIGCHLD);
|
||||
sa.sa_flags = 0; /* SA_NOCLDSTOP flag is removed */
|
||||
sigaction(SIGCHLD, &sa, (struct sigaction *) 0);
|
||||
#else
|
||||
signal(SIGCHLD,action);
|
||||
#endif
|
||||
#endif /* not HPUX */
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
reset_signal_action()
|
||||
{
|
||||
set_signal_action(SIG_DFL);
|
||||
}
|
||||
|
||||
static RETSIGTYPE
|
||||
chld_changed()
|
||||
{
|
||||
int cpid;
|
||||
int i,n = -1;
|
||||
int statusp;
|
||||
|
||||
for (;;) {
|
||||
#ifdef HAVE_WAITPID
|
||||
cpid = waitpid(-1, &statusp, WUNTRACED|WNOHANG);
|
||||
#else
|
||||
cpid = wait3(&statusp, WUNTRACED|WNOHANG, 0);
|
||||
#endif
|
||||
if (cpid == 0 || cpid == -1)
|
||||
return;
|
||||
for (i = 0; i < last_pty; i++) {
|
||||
if (chld_pid[i] == cpid) {
|
||||
n = i;
|
||||
goto catched;
|
||||
}
|
||||
}
|
||||
rb_raise(rb_eRuntimeError, "fork: %d", cpid);
|
||||
}
|
||||
catched:
|
||||
|
||||
#ifdef IF_STOPPED
|
||||
if (IF_STOPPED(statusp)) { /* suspend */
|
||||
rb_raise(rb_eRuntimeError, "Stopped: %d",cpid);
|
||||
}
|
||||
#else
|
||||
#ifdef WIFSTOPPED
|
||||
if (WIFSTOPPED(statusp)) { /* suspend */
|
||||
rb_raise(rb_eRuntimeError, "Stopped: %d",cpid);
|
||||
}
|
||||
#else
|
||||
---->> Either IF_STOPPED or WIFSTOPPED is needed <<----
|
||||
#endif /* WIFSTOPPED */
|
||||
#endif /* IF_STOPPED */
|
||||
if (n >= 0) {
|
||||
chld_pid[n] = 0;
|
||||
n_pty--;
|
||||
if (n_pty == 0)
|
||||
reset_signal_action();
|
||||
}
|
||||
rb_raise(rb_eRuntimeError, "Child_changed: %d",cpid);
|
||||
}
|
||||
|
||||
static void getDevice _((int*, int*));
|
||||
|
||||
static void
|
||||
establishShell(shellname, info)
|
||||
char *shellname;
|
||||
struct pty_info *info;
|
||||
{
|
||||
static int i,j,master,slave,currentPid;
|
||||
char *p,*getenv();
|
||||
struct passwd *pwent;
|
||||
RETSIGTYPE chld_changed();
|
||||
|
||||
if (shellname[0] == '\0') {
|
||||
if ((p = getenv("SHELL")) != NULL) {
|
||||
shellname = p;
|
||||
}
|
||||
else {
|
||||
pwent = getpwuid(getuid());
|
||||
if (pwent && pwent->pw_shell)
|
||||
shellname = pwent->pw_shell;
|
||||
else
|
||||
shellname = "/bin/sh";
|
||||
}
|
||||
}
|
||||
getDevice(&master,&slave);
|
||||
|
||||
currentPid = getpid();
|
||||
set_signal_action(chld_changed);
|
||||
if((i = vfork()) < 0) {
|
||||
rb_sys_fail("fork failed");
|
||||
}
|
||||
|
||||
if(i == 0) { /* child */
|
||||
int argc;
|
||||
char *argv[1024];
|
||||
currentPid = getpid();
|
||||
|
||||
/*
|
||||
* Set free from process group and controlling terminal
|
||||
*/
|
||||
#ifdef HAVE_SETSID
|
||||
(void) setsid();
|
||||
#else /* HAS_SETSID */
|
||||
# ifdef HAVE_SETPGRP
|
||||
# ifdef SETGRP_VOID
|
||||
if (setpgrp() == -1)
|
||||
perror("setpgrp()");
|
||||
# else /* SETGRP_VOID */
|
||||
if (setpgrp(0, currentPid) == -1)
|
||||
rb_sys_fail("setpgrp()");
|
||||
if ((i = open("/dev/tty", O_RDONLY)) < 0)
|
||||
rb_sys_fail("/dev/tty");
|
||||
else {
|
||||
if (ioctl(i, TIOCNOTTY, (char *)0))
|
||||
perror("ioctl(TIOCNOTTY)");
|
||||
close(i);
|
||||
}
|
||||
# endif /* SETGRP_VOID */
|
||||
# endif /* HAVE_SETPGRP */
|
||||
#endif /* HAS_SETSID */
|
||||
|
||||
/*
|
||||
* obtain new controlling terminal
|
||||
*/
|
||||
#if defined(TIOCSCTTY)
|
||||
close(master);
|
||||
(void) ioctl(slave, TIOCSCTTY, (char *)0);
|
||||
/* errors ignored for sun */
|
||||
#else
|
||||
close(slave);
|
||||
slave = open(SlaveName, O_RDWR);
|
||||
if (slave < 0) {
|
||||
perror("open: pty slave");
|
||||
_exit(1);
|
||||
}
|
||||
close(master);
|
||||
#endif
|
||||
dup2(slave,0);
|
||||
dup2(slave,1);
|
||||
dup2(slave,2);
|
||||
close(slave);
|
||||
|
||||
seteuid(getuid());
|
||||
|
||||
argc = 0;
|
||||
for (i = 0; shellname[i];) {
|
||||
while (isspace(shellname[i])) i++;
|
||||
for (j = i; shellname[j] && !isspace(shellname[j]); j++);
|
||||
argv[argc] = (char*)xmalloc(j-i+1);
|
||||
strncpy(argv[argc],&shellname[i],j-i);
|
||||
argv[argc][j-i] = 0;
|
||||
i = j;
|
||||
argc++;
|
||||
}
|
||||
argv[argc] = NULL;
|
||||
execvp(argv[0],argv);
|
||||
sleep(1);
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
close(slave);
|
||||
|
||||
if (n_pty == last_pty) {
|
||||
chld_pid[n_pty] = i;
|
||||
n_pty++;
|
||||
last_pty++;
|
||||
}
|
||||
else {
|
||||
for (j = 0; j < last_pty; j++) {
|
||||
if (chld_pid[j] == 0) {
|
||||
chld_pid[j] = i;
|
||||
n_pty++;
|
||||
}
|
||||
}
|
||||
}
|
||||
info->child_pid = i;
|
||||
info->fd = master;
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENPTY
|
||||
/*
|
||||
* Use openpty(3) of 4.3BSD Reno and later,
|
||||
* or the same interface function.
|
||||
*/
|
||||
static void
|
||||
getDevice(master,slave)
|
||||
int *master,*slave;
|
||||
{
|
||||
if (openpty(master, slave, SlaveName,
|
||||
(struct termios *)0, (struct winsize *)0) == -1) {
|
||||
rb_raise(rb_eRuntimeError, "openpty() failed");
|
||||
}
|
||||
}
|
||||
#else /* HAVE_OPENPTY */
|
||||
#ifdef HAVE__GETPTY
|
||||
static void
|
||||
getDevice(master,slave)
|
||||
int *master,*slave;
|
||||
{
|
||||
char *name;
|
||||
|
||||
if (!(name = _getpty(master, O_RDWR, 0622, 0))) {
|
||||
rb_raise(rb_eRuntimeError, "_getpty() failed");
|
||||
}
|
||||
|
||||
*slave = open(name, O_RDWR);
|
||||
strcpy(SlaveName, name);
|
||||
}
|
||||
#else /* HAVE__GETPTY */
|
||||
static void
|
||||
getDevice(master,slave)
|
||||
int *master,*slave;
|
||||
{
|
||||
char **p;
|
||||
int i,j;
|
||||
char MasterName[DEVICELEN];
|
||||
|
||||
#ifdef HAVE_DEV_PTMX
|
||||
char *pn;
|
||||
void (*s)();
|
||||
|
||||
extern char *ptsname(int);
|
||||
extern int unlockpt(int);
|
||||
extern int grantpt(int);
|
||||
|
||||
if((i = open("/dev/ptmx", O_RDWR, 0)) != -1) {
|
||||
s = signal(SIGCHLD, SIG_DFL);
|
||||
if(grantpt(i) != -1) {
|
||||
signal(SIGCHLD, s);
|
||||
if(unlockpt(i) != -1) {
|
||||
if((pn = ptsname(i)) != NULL) {
|
||||
if((j = open(pn, O_RDWR, 0)) != -1) {
|
||||
#if defined I_PUSH
|
||||
if(ioctl(j, I_PUSH, "ptem") != -1) {
|
||||
if(ioctl(j, I_PUSH, "ldterm") != -1) {
|
||||
#endif
|
||||
*master = i;
|
||||
*slave = j;
|
||||
strcpy(SlaveName, pn);
|
||||
return;
|
||||
#if defined I_PUSH
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
close(i);
|
||||
}
|
||||
rb_raise(rb_eRuntimeError, "Cannot get Master/Slave device");
|
||||
#else
|
||||
for (p = deviceNo; *p != NULL; p++) {
|
||||
sprintf(MasterName ,MasterDevice,*p);
|
||||
if ((i = open(MasterName,O_RDWR,0)) >= 0) {
|
||||
*master = i;
|
||||
sprintf(SlaveName ,SlaveDevice,*p);
|
||||
if ((j = open(SlaveName,O_RDWR,0)) >= 0) {
|
||||
*slave = j;
|
||||
chown(SlaveName, getuid(), getgid());
|
||||
chmod(SlaveName, 0622);
|
||||
return;
|
||||
}
|
||||
close(i);
|
||||
}
|
||||
}
|
||||
rb_raise(rb_eRuntimeError, "Cannot get %s\n", SlaveDevice);
|
||||
#endif
|
||||
}
|
||||
#endif /* HAVE__GETPTY */
|
||||
#endif /* HAVE_OPENPTY */
|
||||
|
||||
static void
|
||||
freeDevice()
|
||||
{
|
||||
chmod(SlaveName, 0666);
|
||||
chown(SlaveName, 0, 0);
|
||||
}
|
||||
|
||||
/* ruby function: getpty */
|
||||
static VALUE
|
||||
pty_getpty(self, shell)
|
||||
VALUE self, shell;
|
||||
{
|
||||
VALUE res;
|
||||
struct pty_info info;
|
||||
OpenFile *wfptr,*rfptr;
|
||||
NEWOBJ(rport, struct RFile);
|
||||
NEWOBJ(wport, struct RFile);
|
||||
|
||||
if (n_pty == MAX_PTY+1) {
|
||||
rb_raise(rb_eRuntimeError, "Too many ptys are open");
|
||||
}
|
||||
|
||||
OBJSETUP(rport, rb_cFile, T_FILE);
|
||||
MakeOpenFile(rport, rfptr);
|
||||
|
||||
OBJSETUP(wport, rb_cFile, T_FILE);
|
||||
MakeOpenFile(wport, wfptr);
|
||||
|
||||
establishShell(RSTRING(shell)->ptr,&info);
|
||||
|
||||
rfptr->mode = rb_io_mode_flags("r");
|
||||
rfptr->f = fdopen(info.fd, "r");
|
||||
rfptr->path = strdup(RSTRING(shell)->ptr);
|
||||
|
||||
wfptr->mode = rb_io_mode_flags("w");
|
||||
wfptr->f = fdopen(dup(info.fd), "w");
|
||||
wfptr->path = strdup(RSTRING(shell)->ptr);
|
||||
|
||||
res = rb_ary_new2(2);
|
||||
rb_ary_store(res,0,(VALUE)rport);
|
||||
rb_ary_store(res,1,(VALUE)wport);
|
||||
rb_ary_store(res,2,INT2FIX(info.child_pid));
|
||||
|
||||
if (rb_iterator_p()) {
|
||||
rb_yield((VALUE)res);
|
||||
reset_signal_action();
|
||||
return Qnil;
|
||||
}
|
||||
else {
|
||||
return (VALUE)res;
|
||||
}
|
||||
}
|
||||
|
||||
/* ruby function: protect_signal */
|
||||
static VALUE
|
||||
pty_protect(self)
|
||||
VALUE self;
|
||||
{
|
||||
reset_signal_action();
|
||||
rb_yield(Qnil);
|
||||
set_signal_action(chld_changed);
|
||||
return self;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
pty_reset_signal(self)
|
||||
VALUE self;
|
||||
{
|
||||
reset_signal_action();
|
||||
return self;
|
||||
}
|
||||
|
||||
static VALUE cPTY;
|
||||
|
||||
void
|
||||
Init_pty()
|
||||
{
|
||||
cPTY = rb_define_module("PTY");
|
||||
rb_define_module_function(cPTY,"getpty",pty_getpty,1);
|
||||
rb_define_module_function(cPTY,"spawn",pty_getpty,1);
|
||||
rb_define_module_function(cPTY,"protect_signal",pty_protect,0);
|
||||
rb_define_module_function(cPTY,"reset_signal",pty_reset_signal,0);
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
require 'pty'
|
||||
|
||||
if ARGV.size == 0 then
|
||||
ofile = "typescript"
|
||||
else
|
||||
ofile = ARGV[0]
|
||||
end
|
||||
|
||||
logfile = File.open(ofile,"a")
|
||||
|
||||
system "stty -echo raw lnext ^_"
|
||||
|
||||
PTY.spawn("/bin/csh") do
|
||||
|r_pty,w_pty,pid|
|
||||
|
||||
Thread.new do
|
||||
while true
|
||||
w_pty.print STDIN.getc.chr
|
||||
w_pty.flush
|
||||
end
|
||||
end
|
||||
|
||||
begin
|
||||
while true
|
||||
c = r_pty.getc
|
||||
next if c.nil?
|
||||
print c.chr
|
||||
STDOUT.flush
|
||||
logfile.print c.chr
|
||||
end
|
||||
rescue
|
||||
# print $@,':',$!,"\n"
|
||||
logfile.close
|
||||
end
|
||||
end
|
||||
|
||||
system "stty echo -raw lnext ^v"
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
#
|
||||
# old-fashioned 'shl' like program
|
||||
# by A. Ito
|
||||
#
|
||||
# commands:
|
||||
# c creates new shell
|
||||
# C-z suspends shell
|
||||
# p lists all shell
|
||||
# 0,1,... choose shell
|
||||
# q quit
|
||||
|
||||
require 'pty'
|
||||
|
||||
$shells = []
|
||||
$n_shells = 0
|
||||
|
||||
$r_pty = nil
|
||||
$w_pty = nil
|
||||
|
||||
def writer
|
||||
PTY.protect_signal do
|
||||
system "stty -echo raw"
|
||||
end
|
||||
begin
|
||||
while true
|
||||
c = STDIN.getc
|
||||
if c == 26 then # C-z
|
||||
$reader.raise(nil)
|
||||
return 'Suspend'
|
||||
end
|
||||
$w_pty.print c.chr
|
||||
$w_pty.flush
|
||||
end
|
||||
rescue
|
||||
$reader.raise(nil)
|
||||
return 'Exit'
|
||||
ensure
|
||||
PTY.protect_signal do
|
||||
system "stty echo -raw"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
$reader = Thread.new {
|
||||
while true
|
||||
begin
|
||||
next if $r_pty.nil?
|
||||
c = $r_pty.getc
|
||||
if c.nil? then
|
||||
Thread.stop
|
||||
end
|
||||
print c.chr
|
||||
STDOUT.flush
|
||||
rescue
|
||||
Thread.stop
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
# $reader.raise(nil)
|
||||
|
||||
|
||||
while true
|
||||
print ">> "
|
||||
STDOUT.flush
|
||||
case gets
|
||||
when /^c/i
|
||||
$shells[$n_shells] = PTY.spawn("/bin/csh")
|
||||
$r_pty,$w_pty = $shells[$n_shells]
|
||||
$n_shells += 1
|
||||
$reader.run
|
||||
if writer == 'Exit'
|
||||
$n_shells -= 1
|
||||
$shells[$n_shells] = nil
|
||||
end
|
||||
when /^p/i
|
||||
for i in 0..$n_shells
|
||||
unless $shells[i].nil?
|
||||
print i,"\n"
|
||||
end
|
||||
end
|
||||
when /^([0-9]+)/
|
||||
n = $1.to_i
|
||||
if $shells[n].nil?
|
||||
print "\##{i} doesn't exist\n"
|
||||
else
|
||||
$r_pty,$w_pty = $shells[n]
|
||||
$reader.run
|
||||
if writer == 'Exit' then
|
||||
$shells[n] = nil
|
||||
end
|
||||
end
|
||||
when /^q/i
|
||||
exit
|
||||
end
|
||||
end
|
|
@ -1,6 +1,9 @@
|
|||
require "mkmf"
|
||||
|
||||
dir_config("readline")
|
||||
have_library("user32", nil) if /cygwin/ === PLATFORM
|
||||
have_library("termcap", "tgetnum")
|
||||
have_library("curses", "tgetnum")
|
||||
if have_header("readline/readline.h") and
|
||||
have_header("readline/history.h") and
|
||||
have_library("readline", "readline")
|
||||
|
|
|
@ -19,13 +19,14 @@ static int
|
|||
readline_event()
|
||||
{
|
||||
CHECK_INTS;
|
||||
#ifdef USE_THREAD
|
||||
rb_thread_schedule();
|
||||
#endif
|
||||
}
|
||||
|
||||
static VALUE
|
||||
readline_readline(int argc, VALUE *argv, VALUE self)
|
||||
readline_readline(argc, argv, self)
|
||||
int argc;
|
||||
VALUE *argv;
|
||||
VALUE self;
|
||||
{
|
||||
VALUE tmp, add_hist, result;
|
||||
char *prompt = NULL;
|
||||
|
@ -47,7 +48,9 @@ readline_readline(int argc, VALUE *argv, VALUE self)
|
|||
}
|
||||
|
||||
static VALUE
|
||||
readline_s_set_completion_proc(VALUE self, VALUE proc)
|
||||
readline_s_set_completion_proc(self, proc)
|
||||
VALUE self;
|
||||
VALUE proc;
|
||||
{
|
||||
if (!rb_respond_to(proc, rb_intern("call")))
|
||||
rb_raise(rb_eArgError, "argument have to respond to `call'");
|
||||
|
@ -55,25 +58,32 @@ readline_s_set_completion_proc(VALUE self, VALUE proc)
|
|||
}
|
||||
|
||||
static VALUE
|
||||
readline_s_get_completion_proc(VALUE self)
|
||||
readline_s_get_completion_proc(self)
|
||||
VALUE self;
|
||||
{
|
||||
return rb_iv_get(mReadline, COMPLETION_PROC);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
readline_s_set_completion_case_fold(VALUE self, VALUE val)
|
||||
readline_s_set_completion_case_fold(self, val)
|
||||
VALUE self;
|
||||
VALUE val;
|
||||
{
|
||||
return rb_iv_set(mReadline, COMPLETION_CASE_FOLD, val);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
readline_s_get_completion_case_fold(VALUE self)
|
||||
readline_s_get_completion_case_fold(self)
|
||||
VALUE self;
|
||||
{
|
||||
return rb_iv_get(mReadline, COMPLETION_CASE_FOLD);
|
||||
}
|
||||
|
||||
static char **
|
||||
readline_attempted_completion_function(char *text, int start, int end)
|
||||
readline_attempted_completion_function(text, start, end)
|
||||
char *text;
|
||||
int start;
|
||||
int end;
|
||||
{
|
||||
VALUE proc, ary, temp;
|
||||
char **result;
|
||||
|
@ -81,6 +91,8 @@ readline_attempted_completion_function(char *text, int start, int end)
|
|||
int i, matches;
|
||||
|
||||
proc = rb_iv_get(mReadline, COMPLETION_PROC);
|
||||
if (NIL_P(proc))
|
||||
return NULL;
|
||||
rl_attempted_completion_over = 1;
|
||||
case_fold = RTEST(rb_iv_get(mReadline, COMPLETION_CASE_FOLD));
|
||||
ary = rb_funcall(proc, rb_intern("call"), 1, rb_str_new2(text));
|
||||
|
@ -133,27 +145,32 @@ readline_attempted_completion_function(char *text, int start, int end)
|
|||
}
|
||||
|
||||
static VALUE
|
||||
readline_s_vi_editing_mode(VALUE self)
|
||||
readline_s_vi_editing_mode(self)
|
||||
VALUE self;
|
||||
{
|
||||
rl_vi_editing_mode();
|
||||
rl_vi_editing_mode(1,0);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
readline_s_emacs_editing_mode(VALUE self)
|
||||
readline_s_emacs_editing_mode(self)
|
||||
VALUE self;
|
||||
{
|
||||
rl_emacs_editing_mode();
|
||||
rl_emacs_editing_mode(1,0);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
hist_to_s(VALUE self)
|
||||
hist_to_s(self)
|
||||
VALUE self;
|
||||
{
|
||||
return rb_str_new2("HISTORY");
|
||||
}
|
||||
|
||||
static VALUE
|
||||
hist_get(VALUE self, VALUE index)
|
||||
hist_get(self, index)
|
||||
VALUE self;
|
||||
VALUE index;
|
||||
{
|
||||
HISTORY_STATE *state;
|
||||
int i;
|
||||
|
@ -167,7 +184,10 @@ hist_get(VALUE self, VALUE index)
|
|||
}
|
||||
|
||||
static VALUE
|
||||
hist_set(VALUE self, VALUE index, VALUE str)
|
||||
hist_set(self, index, str)
|
||||
VALUE self;
|
||||
VALUE index;
|
||||
VALUE str;
|
||||
{
|
||||
HISTORY_STATE *state;
|
||||
int i;
|
||||
|
@ -182,15 +202,19 @@ hist_set(VALUE self, VALUE index, VALUE str)
|
|||
}
|
||||
|
||||
static VALUE
|
||||
hist_push(VALUE self, VALUE str)
|
||||
hist_push(self, str)
|
||||
VALUE self;
|
||||
VALUE str;
|
||||
{
|
||||
add_history(STR2CSTR(str));
|
||||
return self;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
hist_push_method(int argc, VALUE *argv,
|
||||
VALUE self)
|
||||
hist_push_method(argc, argv, self)
|
||||
int argc;
|
||||
VALUE *argv;
|
||||
VALUE self;
|
||||
{
|
||||
VALUE str;
|
||||
|
||||
|
@ -202,7 +226,8 @@ hist_push_method(int argc, VALUE *argv,
|
|||
}
|
||||
|
||||
static VALUE
|
||||
hist_pop(VALUE self)
|
||||
hist_pop(self)
|
||||
VALUE self;
|
||||
{
|
||||
HISTORY_STATE *state;
|
||||
HIST_ENTRY *entry;
|
||||
|
@ -217,7 +242,8 @@ hist_pop(VALUE self)
|
|||
}
|
||||
|
||||
static VALUE
|
||||
hist_shift(VALUE self)
|
||||
hist_shift(self)
|
||||
VALUE self;
|
||||
{
|
||||
HISTORY_STATE *state;
|
||||
HIST_ENTRY *entry;
|
||||
|
@ -232,7 +258,8 @@ hist_shift(VALUE self)
|
|||
}
|
||||
|
||||
static VALUE
|
||||
hist_each(VALUE self)
|
||||
hist_each(self)
|
||||
VALUE self;
|
||||
{
|
||||
HISTORY_STATE *state;
|
||||
int i;
|
||||
|
@ -241,11 +268,12 @@ hist_each(VALUE self)
|
|||
for (i = 0; i < state->length; i++) {
|
||||
rb_yield(rb_str_new2(state->entries[i]->line));
|
||||
}
|
||||
return Qnil;
|
||||
return self;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
hist_length(VALUE self)
|
||||
hist_length(self)
|
||||
VALUE self;
|
||||
{
|
||||
HISTORY_STATE *state;
|
||||
|
||||
|
@ -254,7 +282,8 @@ hist_length(VALUE self)
|
|||
}
|
||||
|
||||
static VALUE
|
||||
hist_empty_p(VALUE self)
|
||||
hist_empty_p(self)
|
||||
VALUE self;
|
||||
{
|
||||
HISTORY_STATE *state;
|
||||
|
||||
|
@ -266,7 +295,9 @@ hist_empty_p(VALUE self)
|
|||
}
|
||||
|
||||
static VALUE
|
||||
hist_delete_at(VALUE self, VALUE index)
|
||||
hist_delete_at(self, index)
|
||||
VALUE self;
|
||||
VALUE index;
|
||||
{
|
||||
HISTORY_STATE *state;
|
||||
HIST_ENTRY *entry;
|
||||
|
@ -282,7 +313,9 @@ hist_delete_at(VALUE self, VALUE index)
|
|||
}
|
||||
|
||||
static VALUE
|
||||
filename_completion_proc_call(VALUE self, VALUE str)
|
||||
filename_completion_proc_call(self, str)
|
||||
VALUE self;
|
||||
VALUE str;
|
||||
{
|
||||
VALUE result;
|
||||
char **matches;
|
||||
|
@ -307,7 +340,9 @@ filename_completion_proc_call(VALUE self, VALUE str)
|
|||
}
|
||||
|
||||
static VALUE
|
||||
username_completion_proc_call(VALUE self, VALUE str)
|
||||
username_completion_proc_call(self, str)
|
||||
VALUE self;
|
||||
VALUE str;
|
||||
{
|
||||
VALUE result;
|
||||
char **matches;
|
||||
|
@ -332,7 +367,7 @@ username_completion_proc_call(VALUE self, VALUE str)
|
|||
}
|
||||
|
||||
void
|
||||
Init_readline(void)
|
||||
Init_readline()
|
||||
{
|
||||
VALUE histary, fcomp, ucomp;
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
MANIFEST
|
||||
_sdbm.c
|
||||
extconf.rb
|
||||
init.c
|
||||
sdbm.h
|
|
@ -0,0 +1,977 @@
|
|||
/*
|
||||
* sdbm - ndbm work-alike hashed database library
|
||||
* based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
|
||||
* author: oz@nexus.yorku.ca
|
||||
* status: public domain.
|
||||
*
|
||||
* core routines
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
/*char sdbm_rcsid[] = "$Id$";*/
|
||||
#endif
|
||||
|
||||
#include "sdbm.h"
|
||||
#include "config.h"
|
||||
|
||||
/*
|
||||
* sdbm - ndbm work-alike hashed database library
|
||||
* tuning and portability constructs [not nearly enough]
|
||||
* author: oz@nexus.yorku.ca
|
||||
*/
|
||||
|
||||
#define BYTESIZ 8
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef BSD42
|
||||
#define SEEK_SET L_SET
|
||||
#define memset(s,c,n) bzero(s, n) /* only when c is zero */
|
||||
#define memcpy(s1,s2,n) bcopy(s2, s1, n)
|
||||
#define memcmp(s1,s2,n) bcmp(s1,s2,n)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* important tuning parms (hah)
|
||||
*/
|
||||
|
||||
#define SEEDUPS /* always detect duplicates */
|
||||
#define BADMESS /* generate a message for worst case:
|
||||
cannot make room after SPLTMAX splits */
|
||||
/*
|
||||
* misc
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
#define debug(x) printf x
|
||||
#else
|
||||
#define debug(x)
|
||||
#endif
|
||||
|
||||
#ifdef BIG_E
|
||||
#define GET_SHORT(p, i) (((unsigned)((unsigned char *)(p))[(i)*2] << 8) + (((unsigned char *)(p))[(i)*2 + 1]))
|
||||
#define PUT_SHORT(p, i, s) (((unsigned char *)(p))[(i)*2] = (unsigned char)((s) >> 8), ((unsigned char *)(p))[(i)*2 + 1] = (unsigned char)(s))
|
||||
#else
|
||||
#define GET_SHORT(p, i) ((p)[i])
|
||||
#define PUT_SHORT(p, i, s) ((p)[i] = (s))
|
||||
#endif
|
||||
|
||||
/*#include "pair.h"*/
|
||||
static int fitpair proto((char *, int));
|
||||
static void putpair proto((char *, datum, datum));
|
||||
static datum getpair proto((char *, datum));
|
||||
static int delpair proto((char *, datum));
|
||||
static int chkpage proto((char *));
|
||||
static datum getnkey proto((char *, int));
|
||||
static void splpage proto((char *, char *, long));
|
||||
#ifdef SEEDUPS
|
||||
static int duppair proto((char *, datum));
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef MSDOS
|
||||
#include <io.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#ifdef BSD42
|
||||
#include <sys/file.h>
|
||||
#else
|
||||
#include <fcntl.h>
|
||||
/*#include <memory.h>*/
|
||||
#endif
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#ifndef EPERM
|
||||
#define EPERM EACCES
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __STDC__
|
||||
#include <stddef.h>
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* externals
|
||||
*/
|
||||
#ifndef sun
|
||||
#ifndef MSDOS
|
||||
extern int errno;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* forward
|
||||
*/
|
||||
static int getdbit proto((DBM *, long));
|
||||
static int setdbit proto((DBM *, long));
|
||||
static int getpage proto((DBM *, long));
|
||||
static datum getnext proto((DBM *));
|
||||
static int makroom proto((DBM *, long, int));
|
||||
|
||||
/*
|
||||
* useful macros
|
||||
*/
|
||||
#define bad(x) ((x).dptr == NULL || (x).dsize < 0)
|
||||
#define exhash(item) sdbm_hash((item).dptr, (item).dsize)
|
||||
#define ioerr(db) ((db)->flags |= DBM_IOERR)
|
||||
|
||||
#define OFF_PAG(off) (long) (off) * PBLKSIZ
|
||||
#define OFF_DIR(off) (long) (off) * DBLKSIZ
|
||||
|
||||
static long masks[] = {
|
||||
000000000000L, 000000000001L, 000000000003L,
|
||||
000000000007L, 000000000017L, 000000000037L,
|
||||
000000000077L, 000000000177L, 000000000377L,
|
||||
000000000777L, 000000001777L, 000000003777L,
|
||||
000000007777L, 000000017777L, 000000037777L,
|
||||
000000077777L, 000000177777L, 000000377777L,
|
||||
000000777777L, 000001777777L, 000003777777L,
|
||||
000007777777L, 000017777777L, 000037777777L,
|
||||
000077777777L, 000177777777L, 000377777777L,
|
||||
000777777777L, 001777777777L, 003777777777L,
|
||||
007777777777L, 017777777777L
|
||||
};
|
||||
|
||||
datum nullitem = {NULL, 0};
|
||||
|
||||
DBM *
|
||||
sdbm_open(file, flags, mode)
|
||||
register char *file;
|
||||
register int flags;
|
||||
register int mode;
|
||||
{
|
||||
register DBM *db;
|
||||
register char *dirname;
|
||||
register char *pagname;
|
||||
register int n;
|
||||
|
||||
if (file == NULL || !*file)
|
||||
return errno = EINVAL, (DBM *) NULL;
|
||||
/*
|
||||
* need space for two seperate filenames
|
||||
*/
|
||||
n = strlen(file) * 2 + strlen(DIRFEXT) + strlen(PAGFEXT) + 2;
|
||||
|
||||
if ((dirname = malloc((unsigned) n)) == NULL)
|
||||
return errno = ENOMEM, (DBM *) NULL;
|
||||
/*
|
||||
* build the file names
|
||||
*/
|
||||
dirname = strcat(strcpy(dirname, file), DIRFEXT);
|
||||
pagname = strcpy(dirname + strlen(dirname) + 1, file);
|
||||
pagname = strcat(pagname, PAGFEXT);
|
||||
|
||||
db = sdbm_prep(dirname, pagname, flags, mode);
|
||||
free((char *) dirname);
|
||||
return db;
|
||||
}
|
||||
|
||||
DBM *
|
||||
sdbm_prep(dirname, pagname, flags, mode)
|
||||
char *dirname;
|
||||
char *pagname;
|
||||
int flags;
|
||||
int mode;
|
||||
{
|
||||
register DBM *db;
|
||||
struct stat dstat;
|
||||
|
||||
if ((db = (DBM *) malloc(sizeof(DBM))) == NULL)
|
||||
return errno = ENOMEM, (DBM *) NULL;
|
||||
|
||||
db->flags = 0;
|
||||
db->hmask = 0;
|
||||
db->blkptr = 0;
|
||||
db->keyptr = 0;
|
||||
/*
|
||||
* adjust user flags so that WRONLY becomes RDWR,
|
||||
* as required by this package. Also set our internal
|
||||
* flag for RDONLY.
|
||||
*/
|
||||
if (flags & O_WRONLY)
|
||||
flags = (flags & ~O_WRONLY) | O_RDWR;
|
||||
if (flags & O_RDONLY)
|
||||
db->flags = DBM_RDONLY;
|
||||
/*
|
||||
* open the files in sequence, and stat the dirfile.
|
||||
* If we fail anywhere, undo everything, return NULL.
|
||||
*/
|
||||
#ifdef MSDOS
|
||||
flags |= O_BINARY;
|
||||
#endif
|
||||
if ((db->pagf = open(pagname, flags, mode)) > -1) {
|
||||
if ((db->dirf = open(dirname, flags, mode)) > -1) {
|
||||
/*
|
||||
* need the dirfile size to establish max bit number.
|
||||
*/
|
||||
if (fstat(db->dirf, &dstat) == 0) {
|
||||
/*
|
||||
* zero size: either a fresh database, or one with a single,
|
||||
* unsplit data page: dirpage is all zeros.
|
||||
*/
|
||||
db->dirbno = (!dstat.st_size) ? 0 : -1;
|
||||
db->pagbno = -1;
|
||||
db->maxbno = dstat.st_size * (long) BYTESIZ;
|
||||
|
||||
(void) memset(db->pagbuf, 0, PBLKSIZ);
|
||||
(void) memset(db->dirbuf, 0, DBLKSIZ);
|
||||
/*
|
||||
* success
|
||||
*/
|
||||
return db;
|
||||
}
|
||||
(void) close(db->dirf);
|
||||
}
|
||||
(void) close(db->pagf);
|
||||
}
|
||||
free((char *) db);
|
||||
return (DBM *) NULL;
|
||||
}
|
||||
|
||||
void
|
||||
sdbm_close(db)
|
||||
register DBM *db;
|
||||
{
|
||||
if (db == NULL)
|
||||
errno = EINVAL;
|
||||
else {
|
||||
(void) close(db->dirf);
|
||||
(void) close(db->pagf);
|
||||
free((char *) db);
|
||||
}
|
||||
}
|
||||
|
||||
datum
|
||||
sdbm_fetch(db, key)
|
||||
register DBM *db;
|
||||
datum key;
|
||||
{
|
||||
if (db == NULL || bad(key))
|
||||
return errno = EINVAL, nullitem;
|
||||
|
||||
if (getpage(db, exhash(key)))
|
||||
return getpair(db->pagbuf, key);
|
||||
|
||||
return ioerr(db), nullitem;
|
||||
}
|
||||
|
||||
int
|
||||
sdbm_delete(db, key)
|
||||
register DBM *db;
|
||||
datum key;
|
||||
{
|
||||
if (db == NULL || bad(key))
|
||||
return errno = EINVAL, -1;
|
||||
if (sdbm_rdonly(db))
|
||||
return errno = EPERM, -1;
|
||||
|
||||
if (getpage(db, exhash(key))) {
|
||||
if (!delpair(db->pagbuf, key))
|
||||
return -1;
|
||||
/*
|
||||
* update the page file
|
||||
*/
|
||||
if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
|
||||
|| write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
|
||||
return ioerr(db), -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ioerr(db), -1;
|
||||
}
|
||||
|
||||
int
|
||||
sdbm_store(db, key, val, flags)
|
||||
register DBM *db;
|
||||
datum key;
|
||||
datum val;
|
||||
int flags;
|
||||
{
|
||||
int need;
|
||||
register long hash;
|
||||
|
||||
if (db == NULL || bad(key))
|
||||
return errno = EINVAL, -1;
|
||||
if (sdbm_rdonly(db))
|
||||
return errno = EPERM, -1;
|
||||
|
||||
need = key.dsize + val.dsize;
|
||||
/*
|
||||
* is the pair too big (or too small) for this database ??
|
||||
*/
|
||||
if (need < 0 || need > PAIRMAX)
|
||||
return errno = EINVAL, -1;
|
||||
|
||||
if (getpage(db, (hash = exhash(key)))) {
|
||||
/*
|
||||
* if we need to replace, delete the key/data pair
|
||||
* first. If it is not there, ignore.
|
||||
*/
|
||||
if (flags == DBM_REPLACE)
|
||||
(void) delpair(db->pagbuf, key);
|
||||
#ifdef SEEDUPS
|
||||
else if (duppair(db->pagbuf, key))
|
||||
return 1;
|
||||
#endif
|
||||
/*
|
||||
* if we do not have enough room, we have to split.
|
||||
*/
|
||||
if (!fitpair(db->pagbuf, need))
|
||||
if (!makroom(db, hash, need))
|
||||
return ioerr(db), -1;
|
||||
/*
|
||||
* we have enough room or split is successful. insert the key,
|
||||
* and update the page file.
|
||||
*/
|
||||
(void) putpair(db->pagbuf, key, val);
|
||||
|
||||
if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
|
||||
|| write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
|
||||
return ioerr(db), -1;
|
||||
/*
|
||||
* success
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ioerr(db), -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* makroom - make room by splitting the overfull page
|
||||
* this routine will attempt to make room for SPLTMAX times before
|
||||
* giving up.
|
||||
*/
|
||||
static int
|
||||
makroom(db, hash, need)
|
||||
register DBM *db;
|
||||
long hash;
|
||||
int need;
|
||||
{
|
||||
long newp;
|
||||
char twin[PBLKSIZ];
|
||||
#ifdef MSDOS
|
||||
char zer[PBLKSIZ];
|
||||
long oldtail;
|
||||
#endif
|
||||
char *pag = db->pagbuf;
|
||||
char *new = twin;
|
||||
register int smax = SPLTMAX;
|
||||
|
||||
do {
|
||||
/*
|
||||
* split the current page
|
||||
*/
|
||||
(void) splpage(pag, new, db->hmask + 1);
|
||||
/*
|
||||
* address of the new page
|
||||
*/
|
||||
newp = (hash & db->hmask) | (db->hmask + 1);
|
||||
debug(("newp: %ld\n", newp));
|
||||
/*
|
||||
* write delay, read avoidence/cache shuffle:
|
||||
* select the page for incoming pair: if key is to go to the new page,
|
||||
* write out the previous one, and copy the new one over, thus making
|
||||
* it the current page. If not, simply write the new page, and we are
|
||||
* still looking at the page of interest. current page is not updated
|
||||
* here, as sdbm_store will do so, after it inserts the incoming pair.
|
||||
*/
|
||||
|
||||
#ifdef MSDOS
|
||||
/*
|
||||
* Fill hole with 0 if made it.
|
||||
* (hole is NOT read as 0)
|
||||
*/
|
||||
oldtail = lseek(db->pagf, 0L, SEEK_END);
|
||||
memset(zer, 0, PBLKSIZ);
|
||||
while (OFF_PAG(newp) > oldtail) {
|
||||
if (lseek(db->pagf, 0L, SEEK_END) < 0 ||
|
||||
write(db->pagf, zer, PBLKSIZ) < 0) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
oldtail += PBLKSIZ;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (hash & (db->hmask + 1)) {
|
||||
if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
|
||||
|| write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
|
||||
return 0;
|
||||
db->pagbno = newp;
|
||||
(void) memcpy(pag, new, PBLKSIZ);
|
||||
}
|
||||
else if (lseek(db->pagf, OFF_PAG(newp), SEEK_SET) < 0
|
||||
|| write(db->pagf, new, PBLKSIZ) < 0)
|
||||
return 0;
|
||||
|
||||
if (!setdbit(db, db->curbit))
|
||||
return 0;
|
||||
/*
|
||||
* see if we have enough room now
|
||||
*/
|
||||
if (fitpair(pag, need))
|
||||
return 1;
|
||||
/*
|
||||
* try again... update curbit and hmask as getpage would have
|
||||
* done. because of our update of the current page, we do not
|
||||
* need to read in anything. BUT we have to write the current
|
||||
* [deferred] page out, as the window of failure is too great.
|
||||
*/
|
||||
db->curbit = 2 * db->curbit +
|
||||
((hash & (db->hmask + 1)) ? 2 : 1);
|
||||
db->hmask |= (db->hmask + 1);
|
||||
|
||||
if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
|
||||
|| write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
|
||||
return 0;
|
||||
|
||||
} while (--smax);
|
||||
/*
|
||||
* if we are here, this is real bad news. After SPLTMAX splits,
|
||||
* we still cannot fit the key. say goodnight.
|
||||
*/
|
||||
#ifdef BADMESS
|
||||
(void) write(2, "sdbm: cannot insert after SPLTMAX attempts.\n", 44);
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* the following two routines will break if
|
||||
* deletions aren't taken into account. (ndbm bug)
|
||||
*/
|
||||
datum
|
||||
sdbm_firstkey(db)
|
||||
register DBM *db;
|
||||
{
|
||||
if (db == NULL)
|
||||
return errno = EINVAL, nullitem;
|
||||
/*
|
||||
* start at page 0
|
||||
*/
|
||||
(void) memset(db->pagbuf, 0, PBLKSIZ);
|
||||
if (lseek(db->pagf, OFF_PAG(0), SEEK_SET) < 0
|
||||
|| read(db->pagf, db->pagbuf, PBLKSIZ) < 0)
|
||||
return ioerr(db), nullitem;
|
||||
db->pagbno = 0;
|
||||
db->blkptr = 0;
|
||||
db->keyptr = 0;
|
||||
|
||||
return getnext(db);
|
||||
}
|
||||
|
||||
datum
|
||||
sdbm_nextkey(db)
|
||||
register DBM *db;
|
||||
{
|
||||
if (db == NULL)
|
||||
return errno = EINVAL, nullitem;
|
||||
return getnext(db);
|
||||
}
|
||||
|
||||
/*
|
||||
* all important binary trie traversal
|
||||
*/
|
||||
static int
|
||||
getpage(db, hash)
|
||||
register DBM *db;
|
||||
register long hash;
|
||||
{
|
||||
register int hbit;
|
||||
register long dbit;
|
||||
register long pagb;
|
||||
|
||||
dbit = 0;
|
||||
hbit = 0;
|
||||
while (dbit < db->maxbno && getdbit(db, dbit))
|
||||
dbit = 2 * dbit + ((hash & ((long) 1 << hbit++)) ? 2 : 1);
|
||||
|
||||
debug(("dbit: %d...", dbit));
|
||||
|
||||
db->curbit = dbit;
|
||||
db->hmask = masks[hbit];
|
||||
|
||||
pagb = hash & db->hmask;
|
||||
/*
|
||||
* see if the block we need is already in memory.
|
||||
* note: this lookaside cache has about 10% hit rate.
|
||||
*/
|
||||
if (pagb != db->pagbno) {
|
||||
/*
|
||||
* note: here, we assume a "hole" is read as 0s.
|
||||
* if not, must zero pagbuf first.
|
||||
*/
|
||||
(void) memset(db->pagbuf, 0, PBLKSIZ);
|
||||
|
||||
if (lseek(db->pagf, OFF_PAG(pagb), SEEK_SET) < 0
|
||||
|| read(db->pagf, db->pagbuf, PBLKSIZ) < 0)
|
||||
return 0;
|
||||
if (!chkpage(db->pagbuf)) {
|
||||
return 0;
|
||||
}
|
||||
db->pagbno = pagb;
|
||||
|
||||
debug(("pag read: %d\n", pagb));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
getdbit(db, dbit)
|
||||
register DBM *db;
|
||||
register long dbit;
|
||||
{
|
||||
register long c;
|
||||
register long dirb;
|
||||
|
||||
c = dbit / BYTESIZ;
|
||||
dirb = c / DBLKSIZ;
|
||||
|
||||
if (dirb != db->dirbno) {
|
||||
if (lseek(db->dirf, OFF_DIR(dirb), SEEK_SET) < 0
|
||||
|| read(db->dirf, db->dirbuf, DBLKSIZ) < 0)
|
||||
return 0;
|
||||
db->dirbno = dirb;
|
||||
|
||||
debug(("dir read: %d\n", dirb));
|
||||
}
|
||||
|
||||
return db->dirbuf[c % DBLKSIZ] & (1 << (dbit % BYTESIZ));
|
||||
}
|
||||
|
||||
static int
|
||||
setdbit(db, dbit)
|
||||
register DBM *db;
|
||||
register long dbit;
|
||||
{
|
||||
register long c;
|
||||
register long dirb;
|
||||
|
||||
c = dbit / BYTESIZ;
|
||||
dirb = c / DBLKSIZ;
|
||||
|
||||
if (dirb != db->dirbno) {
|
||||
if (lseek(db->dirf, OFF_DIR(dirb), SEEK_SET) < 0
|
||||
|| read(db->dirf, db->dirbuf, DBLKSIZ) < 0)
|
||||
return 0;
|
||||
db->dirbno = dirb;
|
||||
|
||||
debug(("dir read: %d\n", dirb));
|
||||
}
|
||||
|
||||
db->dirbuf[c % DBLKSIZ] |= (1 << (dbit % BYTESIZ));
|
||||
|
||||
if (dbit >= db->maxbno)
|
||||
db->maxbno += (long) DBLKSIZ * BYTESIZ;
|
||||
|
||||
if (lseek(db->dirf, OFF_DIR(dirb), SEEK_SET) < 0
|
||||
|| write(db->dirf, db->dirbuf, DBLKSIZ) < 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* getnext - get the next key in the page, and if done with
|
||||
* the page, try the next page in sequence
|
||||
*/
|
||||
static datum
|
||||
getnext(db)
|
||||
register DBM *db;
|
||||
{
|
||||
datum key;
|
||||
|
||||
for (;;) {
|
||||
db->keyptr++;
|
||||
key = getnkey(db->pagbuf, db->keyptr);
|
||||
if (key.dptr != NULL)
|
||||
return key;
|
||||
/*
|
||||
* we either run out, or there is nothing on this page..
|
||||
* try the next one... If we lost our position on the
|
||||
* file, we will have to seek.
|
||||
*/
|
||||
db->keyptr = 0;
|
||||
if (db->pagbno != db->blkptr++)
|
||||
if (lseek(db->pagf, OFF_PAG(db->blkptr), SEEK_SET) < 0)
|
||||
break;
|
||||
db->pagbno = db->blkptr;
|
||||
if (read(db->pagf, db->pagbuf, PBLKSIZ) <= 0)
|
||||
break;
|
||||
if (!chkpage(db->pagbuf)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ioerr(db), nullitem;
|
||||
}
|
||||
|
||||
/* pair.c */
|
||||
/*
|
||||
* sdbm - ndbm work-alike hashed database library
|
||||
* based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
|
||||
* author: oz@nexus.yorku.ca
|
||||
* status: public domain.
|
||||
*
|
||||
* page-level routines
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
/*char pair_rcsid[] = "$Id$";*/
|
||||
#endif
|
||||
|
||||
#ifndef BSD42
|
||||
/*#include <memory.h>*/
|
||||
#endif
|
||||
|
||||
#define exhash(item) sdbm_hash((item).dptr, (item).dsize)
|
||||
|
||||
/*
|
||||
* forward
|
||||
*/
|
||||
static int seepair proto((char *, int, char *, int));
|
||||
|
||||
/*
|
||||
* page format:
|
||||
* +------------------------------+
|
||||
* ino | n | keyoff | datoff | keyoff |
|
||||
* +------------+--------+--------+
|
||||
* | datoff | - - - ----> |
|
||||
* +--------+---------------------+
|
||||
* | F R E E A R E A |
|
||||
* +--------------+---------------+
|
||||
* | <---- - - - | data |
|
||||
* +--------+-----+----+----------+
|
||||
* | key | data | key |
|
||||
* +--------+----------+----------+
|
||||
*
|
||||
* calculating the offsets for free area: if the number
|
||||
* of entries (ino[0]) is zero, the offset to the END of
|
||||
* the free area is the block size. Otherwise, it is the
|
||||
* nth (ino[ino[0]]) entry's offset.
|
||||
*/
|
||||
|
||||
static int
|
||||
fitpair(pag, need)
|
||||
char *pag;
|
||||
int need;
|
||||
{
|
||||
register int n;
|
||||
register int off;
|
||||
register int free;
|
||||
register short *ino = (short *) pag;
|
||||
|
||||
off = ((n = GET_SHORT(ino,0)) > 0) ? GET_SHORT(ino,n) : PBLKSIZ;
|
||||
free = off - (n + 1) * sizeof(short);
|
||||
need += 2 * sizeof(short);
|
||||
|
||||
debug(("free %d need %d\n", free, need));
|
||||
|
||||
return need <= free;
|
||||
}
|
||||
|
||||
static void
|
||||
putpair(pag, key, val)
|
||||
char *pag;
|
||||
datum key;
|
||||
datum val;
|
||||
{
|
||||
register int n;
|
||||
register int off;
|
||||
register short *ino = (short *) pag;
|
||||
|
||||
off = ((n = GET_SHORT(ino,0)) > 0) ? GET_SHORT(ino,n) : PBLKSIZ;
|
||||
/*
|
||||
* enter the key first
|
||||
*/
|
||||
off -= key.dsize;
|
||||
if (key.dsize)
|
||||
(void) memcpy(pag + off, key.dptr, key.dsize);
|
||||
PUT_SHORT(ino,n + 1,off);
|
||||
/*
|
||||
* now the data
|
||||
*/
|
||||
off -= val.dsize;
|
||||
if (val.dsize)
|
||||
(void) memcpy(pag + off, val.dptr, val.dsize);
|
||||
PUT_SHORT(ino,n + 2,off);
|
||||
/*
|
||||
* adjust item count
|
||||
*/
|
||||
PUT_SHORT(ino,0,GET_SHORT(ino,0) + 2);
|
||||
}
|
||||
|
||||
static datum
|
||||
getpair(pag, key)
|
||||
char *pag;
|
||||
datum key;
|
||||
{
|
||||
register int i;
|
||||
register int n;
|
||||
datum val;
|
||||
register short *ino = (short *) pag;
|
||||
|
||||
if ((n = GET_SHORT(ino,0)) == 0)
|
||||
return nullitem;
|
||||
|
||||
if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
|
||||
return nullitem;
|
||||
|
||||
val.dptr = pag + GET_SHORT(ino,i + 1);
|
||||
val.dsize = GET_SHORT(ino,i) - GET_SHORT(ino,i + 1);
|
||||
return val;
|
||||
}
|
||||
|
||||
#ifdef SEEDUPS
|
||||
static int
|
||||
duppair(pag, key)
|
||||
char *pag;
|
||||
datum key;
|
||||
{
|
||||
register short *ino = (short *) pag;
|
||||
return GET_SHORT(ino,0) > 0 &&
|
||||
seepair(pag, GET_SHORT(ino,0), key.dptr, key.dsize) > 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static datum
|
||||
getnkey(pag, num)
|
||||
char *pag;
|
||||
int num;
|
||||
{
|
||||
datum key;
|
||||
register int off;
|
||||
register short *ino = (short *) pag;
|
||||
|
||||
num = num * 2 - 1;
|
||||
if (GET_SHORT(ino,0) == 0 || num > GET_SHORT(ino,0))
|
||||
return nullitem;
|
||||
|
||||
off = (num > 1) ? GET_SHORT(ino,num - 1) : PBLKSIZ;
|
||||
|
||||
key.dptr = pag + GET_SHORT(ino,num);
|
||||
key.dsize = off - GET_SHORT(ino,num);
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
static int
|
||||
delpair(pag, key)
|
||||
char *pag;
|
||||
datum key;
|
||||
{
|
||||
register int n;
|
||||
register int i;
|
||||
register short *ino = (short *) pag;
|
||||
|
||||
if ((n = GET_SHORT(ino,0)) == 0)
|
||||
return 0;
|
||||
|
||||
if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
|
||||
return 0;
|
||||
/*
|
||||
* found the key. if it is the last entry
|
||||
* [i.e. i == n - 1] we just adjust the entry count.
|
||||
* hard case: move all data down onto the deleted pair,
|
||||
* shift offsets onto deleted offsets, and adjust them.
|
||||
* [note: 0 < i < n]
|
||||
*/
|
||||
if (i < n - 1) {
|
||||
register int m;
|
||||
register char *dst = pag + (i == 1 ? PBLKSIZ : GET_SHORT(ino,i - 1));
|
||||
register char *src = pag + GET_SHORT(ino,i + 1);
|
||||
register int zoo = dst - src;
|
||||
|
||||
debug(("free-up %d ", zoo));
|
||||
/*
|
||||
* shift data/keys down
|
||||
*/
|
||||
m = GET_SHORT(ino,i + 1) - GET_SHORT(ino,n);
|
||||
#ifdef DUFF
|
||||
#define MOVB *--dst = *--src
|
||||
|
||||
if (m > 0) {
|
||||
register int loop = (m + 8 - 1) >> 3;
|
||||
|
||||
switch (m & (8 - 1)) {
|
||||
case 0: do {
|
||||
MOVB; case 7: MOVB;
|
||||
case 6: MOVB; case 5: MOVB;
|
||||
case 4: MOVB; case 3: MOVB;
|
||||
case 2: MOVB; case 1: MOVB;
|
||||
} while (--loop);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#ifdef MEMMOVE
|
||||
memmove(dst, src, m);
|
||||
#else
|
||||
while (m--)
|
||||
*--dst = *--src;
|
||||
#endif
|
||||
#endif
|
||||
/*
|
||||
* adjust offset index up
|
||||
*/
|
||||
while (i < n - 1) {
|
||||
PUT_SHORT(ino,i, GET_SHORT(ino,i + 2) + zoo);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
PUT_SHORT(ino, 0, GET_SHORT(ino, 0) - 2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* search for the key in the page.
|
||||
* return offset index in the range 0 < i < n.
|
||||
* return 0 if not found.
|
||||
*/
|
||||
static int
|
||||
seepair(pag, n, key, siz)
|
||||
char *pag;
|
||||
register int n;
|
||||
register char *key;
|
||||
register int siz;
|
||||
{
|
||||
register int i;
|
||||
register int off = PBLKSIZ;
|
||||
register short *ino = (short *) pag;
|
||||
|
||||
for (i = 1; i < n; i += 2) {
|
||||
if (siz == off - GET_SHORT(ino,i) &&
|
||||
memcmp(key, pag + GET_SHORT(ino,i), siz) == 0)
|
||||
return i;
|
||||
off = GET_SHORT(ino,i + 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
splpage(pag, new, sbit)
|
||||
char *pag;
|
||||
char *new;
|
||||
long sbit;
|
||||
{
|
||||
datum key;
|
||||
datum val;
|
||||
|
||||
register int n;
|
||||
register int off = PBLKSIZ;
|
||||
char cur[PBLKSIZ];
|
||||
register short *ino = (short *) cur;
|
||||
|
||||
(void) memcpy(cur, pag, PBLKSIZ);
|
||||
(void) memset(pag, 0, PBLKSIZ);
|
||||
(void) memset(new, 0, PBLKSIZ);
|
||||
|
||||
n = GET_SHORT(ino,0);
|
||||
for (ino++; n > 0; ino += 2) {
|
||||
key.dptr = cur + GET_SHORT(ino,0);
|
||||
key.dsize = off - GET_SHORT(ino,0);
|
||||
val.dptr = cur + GET_SHORT(ino,1);
|
||||
val.dsize = GET_SHORT(ino,0) - GET_SHORT(ino,1);
|
||||
/*
|
||||
* select the page pointer (by looking at sbit) and insert
|
||||
*/
|
||||
(void) putpair((exhash(key) & sbit) ? new : pag, key, val);
|
||||
|
||||
off = GET_SHORT(ino,1);
|
||||
n -= 2;
|
||||
}
|
||||
|
||||
debug(("%d split %d/%d\n", ((short *) cur)[0] / 2,
|
||||
((short *) new)[0] / 2,
|
||||
((short *) pag)[0] / 2));
|
||||
}
|
||||
|
||||
/*
|
||||
* check page sanity:
|
||||
* number of entries should be something
|
||||
* reasonable, and all offsets in the index should be in order.
|
||||
* this could be made more rigorous.
|
||||
*/
|
||||
static int
|
||||
chkpage(pag)
|
||||
char *pag;
|
||||
{
|
||||
register int n;
|
||||
register int off;
|
||||
register short *ino = (short *) pag;
|
||||
|
||||
if ((n = GET_SHORT(ino,0)) < 0 || n > PBLKSIZ / sizeof(short))
|
||||
return 0;
|
||||
|
||||
if (n > 0) {
|
||||
off = PBLKSIZ;
|
||||
for (ino++; n > 0; ino += 2) {
|
||||
if (GET_SHORT(ino,0) > off || GET_SHORT(ino,1) > off ||
|
||||
GET_SHORT(ino,1) > GET_SHORT(ino,0))
|
||||
return 0;
|
||||
off = GET_SHORT(ino,1);
|
||||
n -= 2;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* hash.c */
|
||||
/*
|
||||
* sdbm - ndbm work-alike hashed database library
|
||||
* based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
|
||||
* author: oz@nexus.yorku.ca
|
||||
* status: public domain. keep it that way.
|
||||
*
|
||||
* hashing routine
|
||||
*/
|
||||
|
||||
/*
|
||||
* polynomial conversion ignoring overflows
|
||||
* [this seems to work remarkably well, in fact better
|
||||
* then the ndbm hash function. Replace at your own risk]
|
||||
* use: 65599 nice.
|
||||
* 65587 even better.
|
||||
*/
|
||||
long
|
||||
sdbm_hash(str, len)
|
||||
register char *str;
|
||||
register int len;
|
||||
{
|
||||
register unsigned long n = 0;
|
||||
|
||||
#ifdef DUFF
|
||||
|
||||
#define HASHC n = *str++ + 65599 * n
|
||||
|
||||
if (len > 0) {
|
||||
register int loop = (len + 8 - 1) >> 3;
|
||||
|
||||
switch(len & (8 - 1)) {
|
||||
case 0: do {
|
||||
HASHC; case 7: HASHC;
|
||||
case 6: HASHC; case 5: HASHC;
|
||||
case 4: HASHC; case 3: HASHC;
|
||||
case 2: HASHC; case 1: HASHC;
|
||||
} while (--loop);
|
||||
}
|
||||
|
||||
}
|
||||
#else
|
||||
while (len--)
|
||||
n = ((*str++) & 255) + 65587L * n;
|
||||
#endif
|
||||
return n;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
require 'mkmf'
|
||||
|
||||
create_makefile("sdbm")
|
|
@ -0,0 +1,584 @@
|
|||
/************************************************
|
||||
|
||||
sdbminit.c -
|
||||
|
||||
$Author$
|
||||
$Date$
|
||||
created at: Fri May 7 08:34:24 JST 1999
|
||||
|
||||
Copyright (C) 1995-1998 Yukihiro Matsumoto
|
||||
|
||||
************************************************/
|
||||
|
||||
#include "ruby.h"
|
||||
|
||||
#include "sdbm.h"
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#ifdef USE_CWGUSI
|
||||
# include <sys/errno.h>
|
||||
#endif
|
||||
|
||||
VALUE cSDBM;
|
||||
|
||||
struct dbmdata {
|
||||
int di_size;
|
||||
DBM *di_dbm;
|
||||
};
|
||||
|
||||
static void
|
||||
closed_sdbm()
|
||||
{
|
||||
rb_raise(rb_eRuntimeError, "closed SDBM file");
|
||||
}
|
||||
|
||||
#define GetDBM(obj, dbmp) {\
|
||||
Data_Get_Struct(obj, struct dbmdata, dbmp);\
|
||||
if (dbmp->di_dbm == 0) closed_sdbm();\
|
||||
}
|
||||
|
||||
static void
|
||||
free_sdbm(dbmp)
|
||||
struct dbmdata *dbmp;
|
||||
{
|
||||
|
||||
if (dbmp->di_dbm) sdbm_close(dbmp->di_dbm);
|
||||
free(dbmp);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fsdbm_s_open(argc, argv, klass)
|
||||
int argc;
|
||||
VALUE *argv;
|
||||
VALUE klass;
|
||||
{
|
||||
VALUE file, vmode;
|
||||
DBM *dbm;
|
||||
struct dbmdata *dbmp;
|
||||
int mode;
|
||||
VALUE obj;
|
||||
|
||||
if (rb_scan_args(argc, argv, "11", &file, &vmode) == 1) {
|
||||
mode = 0666; /* default value */
|
||||
}
|
||||
else if (NIL_P(vmode)) {
|
||||
mode = -1; /* return nil if DB not exist */
|
||||
}
|
||||
else {
|
||||
mode = NUM2INT(vmode);
|
||||
}
|
||||
Check_SafeStr(file);
|
||||
|
||||
dbm = 0;
|
||||
if (mode >= 0)
|
||||
dbm = sdbm_open(RSTRING(file)->ptr, O_RDWR|O_CREAT, mode);
|
||||
if (!dbm)
|
||||
dbm = sdbm_open(RSTRING(file)->ptr, O_RDWR, mode);
|
||||
if (!dbm)
|
||||
dbm = sdbm_open(RSTRING(file)->ptr, O_RDONLY, mode);
|
||||
|
||||
if (!dbm) {
|
||||
if (mode == -1) return Qnil;
|
||||
rb_sys_fail(RSTRING(file)->ptr);
|
||||
}
|
||||
|
||||
obj = Data_Make_Struct(klass,struct dbmdata,0,free_sdbm,dbmp);
|
||||
dbmp->di_dbm = dbm;
|
||||
dbmp->di_size = -1;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fsdbm_close(obj)
|
||||
VALUE obj;
|
||||
{
|
||||
struct dbmdata *dbmp;
|
||||
|
||||
Data_Get_Struct(obj, struct dbmdata, dbmp);
|
||||
if (dbmp->di_dbm == 0) closed_sdbm();
|
||||
sdbm_close(dbmp->di_dbm);
|
||||
dbmp->di_dbm = 0;
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fsdbm_fetch(obj, keystr)
|
||||
VALUE obj, keystr;
|
||||
{
|
||||
datum key, value;
|
||||
struct dbmdata *dbmp;
|
||||
DBM *dbm;
|
||||
|
||||
Check_Type(keystr, T_STRING);
|
||||
key.dptr = RSTRING(keystr)->ptr;
|
||||
key.dsize = RSTRING(keystr)->len;
|
||||
|
||||
GetDBM(obj, dbmp);
|
||||
dbm = dbmp->di_dbm;
|
||||
value = sdbm_fetch(dbm, key);
|
||||
if (value.dptr == 0) {
|
||||
return Qnil;
|
||||
}
|
||||
return rb_tainted_str_new(value.dptr, value.dsize);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fsdbm_indexes(argc, argv, obj)
|
||||
int argc;
|
||||
VALUE *argv;
|
||||
VALUE obj;
|
||||
{
|
||||
VALUE new;
|
||||
int i;
|
||||
|
||||
new = rb_ary_new2(argc);
|
||||
for (i=0; i<argc; i++) {
|
||||
rb_ary_push(new, fsdbm_fetch(obj, argv[i]));
|
||||
}
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fsdbm_delete(obj, keystr)
|
||||
VALUE obj, keystr;
|
||||
{
|
||||
datum key, value;
|
||||
struct dbmdata *dbmp;
|
||||
DBM *dbm;
|
||||
|
||||
rb_secure(4);
|
||||
Check_Type(keystr, T_STRING);
|
||||
key.dptr = RSTRING(keystr)->ptr;
|
||||
key.dsize = RSTRING(keystr)->len;
|
||||
|
||||
GetDBM(obj, dbmp);
|
||||
dbm = dbmp->di_dbm;
|
||||
|
||||
value = sdbm_fetch(dbm, key);
|
||||
if (value.dptr == 0) {
|
||||
if (rb_iterator_p()) rb_yield(keystr);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
if (sdbm_delete(dbm, key)) {
|
||||
dbmp->di_size = -1;
|
||||
rb_raise(rb_eRuntimeError, "dbm_delete failed");
|
||||
}
|
||||
else if (dbmp->di_size >= 0) {
|
||||
dbmp->di_size--;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fsdbm_shift(obj)
|
||||
VALUE obj;
|
||||
{
|
||||
datum key, val;
|
||||
struct dbmdata *dbmp;
|
||||
DBM *dbm;
|
||||
VALUE keystr, valstr;
|
||||
|
||||
rb_secure(4);
|
||||
GetDBM(obj, dbmp);
|
||||
dbm = dbmp->di_dbm;
|
||||
|
||||
key = sdbm_firstkey(dbm);
|
||||
if (!key.dptr) return Qnil;
|
||||
val = sdbm_fetch(dbm, key);
|
||||
sdbm_delete(dbm, key);
|
||||
|
||||
keystr = rb_tainted_str_new(key.dptr, key.dsize);
|
||||
valstr = rb_tainted_str_new(val.dptr, val.dsize);
|
||||
return rb_assoc_new(keystr, valstr);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fsdbm_delete_if(obj)
|
||||
VALUE obj;
|
||||
{
|
||||
datum key, val;
|
||||
struct dbmdata *dbmp;
|
||||
DBM *dbm;
|
||||
VALUE keystr, valstr;
|
||||
|
||||
rb_secure(4);
|
||||
GetDBM(obj, dbmp);
|
||||
dbm = dbmp->di_dbm;
|
||||
for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
|
||||
val = sdbm_fetch(dbm, key);
|
||||
keystr = rb_tainted_str_new(key.dptr, key.dsize);
|
||||
valstr = rb_tainted_str_new(val.dptr, val.dsize);
|
||||
if (RTEST(rb_yield(rb_assoc_new(keystr, valstr)))) {
|
||||
if (sdbm_delete(dbm, key)) {
|
||||
rb_raise(rb_eRuntimeError, "sdbm_delete failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fsdbm_clear(obj)
|
||||
VALUE obj;
|
||||
{
|
||||
datum key;
|
||||
struct dbmdata *dbmp;
|
||||
DBM *dbm;
|
||||
|
||||
rb_secure(4);
|
||||
GetDBM(obj, dbmp);
|
||||
dbm = dbmp->di_dbm;
|
||||
dbmp->di_size = -1;
|
||||
for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
|
||||
if (sdbm_delete(dbm, key)) {
|
||||
rb_raise(rb_eRuntimeError, "sdbm_delete failed");
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fsdbm_invert(obj)
|
||||
VALUE obj;
|
||||
{
|
||||
datum key, val;
|
||||
struct dbmdata *dbmp;
|
||||
DBM *dbm;
|
||||
VALUE keystr, valstr;
|
||||
VALUE hash = rb_hash_new();
|
||||
|
||||
GetDBM(obj, dbmp);
|
||||
dbm = dbmp->di_dbm;
|
||||
for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
|
||||
val = sdbm_fetch(dbm, key);
|
||||
keystr = rb_tainted_str_new(key.dptr, key.dsize);
|
||||
valstr = rb_tainted_str_new(val.dptr, val.dsize);
|
||||
rb_hash_aset(hash, valstr, keystr);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
each_pair(obj)
|
||||
VALUE obj;
|
||||
{
|
||||
return rb_funcall(obj, rb_intern("each_pair"), 0, 0);
|
||||
}
|
||||
|
||||
static VALUE fsdbm_store _((VALUE,VALUE,VALUE));
|
||||
|
||||
static VALUE
|
||||
update_i(pair, dbm)
|
||||
VALUE pair, dbm;
|
||||
{
|
||||
Check_Type(pair, T_ARRAY);
|
||||
if (RARRAY(pair)->len < 2) {
|
||||
rb_raise(rb_eArgError, "pair must be [key, value]");
|
||||
}
|
||||
fsdbm_store(dbm, RARRAY(pair)->ptr[0], RARRAY(pair)->ptr[1]);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fsdbm_update(obj, other)
|
||||
VALUE obj, other;
|
||||
{
|
||||
rb_iterate(each_pair, other, update_i, obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fsdbm_replace(obj, other)
|
||||
VALUE obj, other;
|
||||
{
|
||||
fsdbm_clear(obj);
|
||||
rb_iterate(each_pair, other, update_i, obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fsdbm_store(obj, keystr, valstr)
|
||||
VALUE obj, keystr, valstr;
|
||||
{
|
||||
datum key, val;
|
||||
struct dbmdata *dbmp;
|
||||
DBM *dbm;
|
||||
|
||||
if (valstr == Qnil) {
|
||||
fsdbm_delete(obj, keystr);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
rb_secure(4);
|
||||
keystr = rb_obj_as_string(keystr);
|
||||
|
||||
key.dptr = RSTRING(keystr)->ptr;
|
||||
key.dsize = RSTRING(keystr)->len;
|
||||
|
||||
if (NIL_P(valstr)) return fsdbm_delete(obj, keystr);
|
||||
|
||||
valstr = rb_obj_as_string(valstr);
|
||||
val.dptr = RSTRING(valstr)->ptr;
|
||||
val.dsize = RSTRING(valstr)->len;
|
||||
|
||||
Data_Get_Struct(obj, struct dbmdata, dbmp);
|
||||
dbmp->di_size = -1;
|
||||
dbm = dbmp->di_dbm;
|
||||
if (sdbm_store(dbm, key, val, DBM_REPLACE)) {
|
||||
#ifdef HAVE_DBM_CLAERERR
|
||||
sdbm_clearerr(dbm);
|
||||
#endif
|
||||
if (errno == EPERM) rb_sys_fail(0);
|
||||
rb_raise(rb_eRuntimeError, "sdbm_store failed");
|
||||
}
|
||||
|
||||
return valstr;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fsdbm_length(obj)
|
||||
VALUE obj;
|
||||
{
|
||||
datum key;
|
||||
struct dbmdata *dbmp;
|
||||
DBM *dbm;
|
||||
int i = 0;
|
||||
|
||||
Data_Get_Struct(obj, struct dbmdata, dbmp);
|
||||
if (dbmp->di_size > 0) return INT2FIX(dbmp->di_size);
|
||||
dbm = dbmp->di_dbm;
|
||||
|
||||
for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
|
||||
i++;
|
||||
}
|
||||
dbmp->di_size = i;
|
||||
|
||||
return INT2FIX(i);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fsdbm_empty_p(obj)
|
||||
VALUE obj;
|
||||
{
|
||||
datum key;
|
||||
struct dbmdata *dbmp;
|
||||
DBM *dbm;
|
||||
int i = 0;
|
||||
|
||||
Data_Get_Struct(obj, struct dbmdata, dbmp);
|
||||
if (dbmp->di_size < 0) {
|
||||
dbm = dbmp->di_dbm;
|
||||
|
||||
for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
i = dbmp->di_size;
|
||||
}
|
||||
if (i == 0) return Qtrue;
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fsdbm_each_value(obj)
|
||||
VALUE obj;
|
||||
{
|
||||
datum key, val;
|
||||
struct dbmdata *dbmp;
|
||||
DBM *dbm;
|
||||
|
||||
GetDBM(obj, dbmp);
|
||||
dbm = dbmp->di_dbm;
|
||||
for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
|
||||
val = sdbm_fetch(dbm, key);
|
||||
rb_yield(rb_tainted_str_new(val.dptr, val.dsize));
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fsdbm_each_key(obj)
|
||||
VALUE obj;
|
||||
{
|
||||
datum key;
|
||||
struct dbmdata *dbmp;
|
||||
DBM *dbm;
|
||||
|
||||
GetDBM(obj, dbmp);
|
||||
dbm = dbmp->di_dbm;
|
||||
for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
|
||||
rb_yield(rb_tainted_str_new(key.dptr, key.dsize));
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fsdbm_each_pair(obj)
|
||||
VALUE obj;
|
||||
{
|
||||
datum key, val;
|
||||
DBM *dbm;
|
||||
struct dbmdata *dbmp;
|
||||
VALUE keystr, valstr;
|
||||
|
||||
GetDBM(obj, dbmp);
|
||||
dbm = dbmp->di_dbm;
|
||||
|
||||
for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
|
||||
val = sdbm_fetch(dbm, key);
|
||||
keystr = rb_tainted_str_new(key.dptr, key.dsize);
|
||||
valstr = rb_tainted_str_new(val.dptr, val.dsize);
|
||||
rb_yield(rb_assoc_new(keystr, valstr));
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fsdbm_keys(obj)
|
||||
VALUE obj;
|
||||
{
|
||||
datum key;
|
||||
struct dbmdata *dbmp;
|
||||
DBM *dbm;
|
||||
VALUE ary;
|
||||
|
||||
GetDBM(obj, dbmp);
|
||||
dbm = dbmp->di_dbm;
|
||||
|
||||
ary = rb_ary_new();
|
||||
for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
|
||||
rb_ary_push(ary, rb_tainted_str_new(key.dptr, key.dsize));
|
||||
}
|
||||
|
||||
return ary;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fsdbm_values(obj)
|
||||
VALUE obj;
|
||||
{
|
||||
datum key, val;
|
||||
struct dbmdata *dbmp;
|
||||
DBM *dbm;
|
||||
VALUE ary;
|
||||
|
||||
GetDBM(obj, dbmp);
|
||||
dbm = dbmp->di_dbm;
|
||||
|
||||
ary = rb_ary_new();
|
||||
for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
|
||||
val = sdbm_fetch(dbm, key);
|
||||
rb_ary_push(ary, rb_tainted_str_new(val.dptr, val.dsize));
|
||||
}
|
||||
|
||||
return ary;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fsdbm_has_key(obj, keystr)
|
||||
VALUE obj, keystr;
|
||||
{
|
||||
datum key, val;
|
||||
struct dbmdata *dbmp;
|
||||
DBM *dbm;
|
||||
|
||||
Check_Type(keystr, T_STRING);
|
||||
key.dptr = RSTRING(keystr)->ptr;
|
||||
key.dsize = RSTRING(keystr)->len;
|
||||
|
||||
GetDBM(obj, dbmp);
|
||||
dbm = dbmp->di_dbm;
|
||||
val = sdbm_fetch(dbm, key);
|
||||
if (val.dptr) return Qtrue;
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fsdbm_has_value(obj, valstr)
|
||||
VALUE obj, valstr;
|
||||
{
|
||||
datum key, val;
|
||||
struct dbmdata *dbmp;
|
||||
DBM *dbm;
|
||||
|
||||
Check_Type(valstr, T_STRING);
|
||||
val.dptr = RSTRING(valstr)->ptr;
|
||||
val.dsize = RSTRING(valstr)->len;
|
||||
|
||||
GetDBM(obj, dbmp);
|
||||
dbm = dbmp->di_dbm;
|
||||
for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
|
||||
val = sdbm_fetch(dbm, key);
|
||||
if (val.dsize == RSTRING(valstr)->len &&
|
||||
memcmp(val.dptr, RSTRING(valstr)->ptr, val.dsize) == 0)
|
||||
return Qtrue;
|
||||
}
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
fsdbm_to_a(obj)
|
||||
VALUE obj;
|
||||
{
|
||||
datum key, val;
|
||||
struct dbmdata *dbmp;
|
||||
DBM *dbm;
|
||||
VALUE ary;
|
||||
|
||||
GetDBM(obj, dbmp);
|
||||
dbm = dbmp->di_dbm;
|
||||
|
||||
ary = rb_ary_new();
|
||||
for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
|
||||
val = sdbm_fetch(dbm, key);
|
||||
rb_ary_push(ary, rb_assoc_new(rb_tainted_str_new(key.dptr, key.dsize),
|
||||
rb_tainted_str_new(val.dptr, val.dsize)));
|
||||
}
|
||||
|
||||
return ary;
|
||||
}
|
||||
|
||||
void
|
||||
Init_sdbm()
|
||||
{
|
||||
cSDBM = rb_define_class("SDBM", rb_cObject);
|
||||
rb_include_module(cSDBM, rb_mEnumerable);
|
||||
|
||||
rb_define_singleton_method(cSDBM, "open", fsdbm_s_open, -1);
|
||||
rb_define_singleton_method(cSDBM, "new", fsdbm_s_open, -1);
|
||||
rb_define_method(cSDBM, "close", fsdbm_close, 0);
|
||||
rb_define_method(cSDBM, "[]", fsdbm_fetch, 1);
|
||||
rb_define_method(cSDBM, "[]=", fsdbm_store, 2);
|
||||
rb_define_method(cSDBM, "indexes", fsdbm_indexes, -1);
|
||||
rb_define_method(cSDBM, "indices", fsdbm_indexes, -1);
|
||||
rb_define_method(cSDBM, "length", fsdbm_length, 0);
|
||||
rb_define_alias(cSDBM, "size", "length");
|
||||
rb_define_method(cSDBM, "empty?", fsdbm_empty_p, 0);
|
||||
rb_define_method(cSDBM, "each", fsdbm_each_pair, 0);
|
||||
rb_define_method(cSDBM, "each_value", fsdbm_each_value, 0);
|
||||
rb_define_method(cSDBM, "each_key", fsdbm_each_key, 0);
|
||||
rb_define_method(cSDBM, "each_pair", fsdbm_each_pair, 0);
|
||||
rb_define_method(cSDBM, "keys", fsdbm_keys, 0);
|
||||
rb_define_method(cSDBM, "values", fsdbm_values, 0);
|
||||
rb_define_method(cSDBM, "shift", fsdbm_shift, 1);
|
||||
rb_define_method(cSDBM, "delete", fsdbm_delete, 1);
|
||||
rb_define_method(cSDBM, "delete_if", fsdbm_delete_if, 0);
|
||||
rb_define_method(cSDBM, "clear", fsdbm_clear, 0);
|
||||
rb_define_method(cSDBM,"invert", fsdbm_invert, 0);
|
||||
rb_define_method(cSDBM,"update", fsdbm_update, 1);
|
||||
rb_define_method(cSDBM,"replace", fsdbm_replace, 1);
|
||||
|
||||
rb_define_method(cSDBM, "include?", fsdbm_has_key, 1);
|
||||
rb_define_method(cSDBM, "has_key?", fsdbm_has_key, 1);
|
||||
rb_define_method(cSDBM, "has_value?", fsdbm_has_value, 1);
|
||||
rb_define_method(cSDBM, "key?", fsdbm_has_key, 1);
|
||||
rb_define_method(cSDBM, "value?", fsdbm_has_value, 1);
|
||||
|
||||
rb_define_method(cSDBM, "to_a", fsdbm_to_a, 0);
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* sdbm - ndbm work-alike hashed database library
|
||||
* based on Per-Ake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
|
||||
* author: oz@nexus.yorku.ca
|
||||
* status: public domain.
|
||||
*/
|
||||
#ifndef _SDBM_H_
|
||||
#define _SDBM_H_
|
||||
|
||||
#define DBLKSIZ 4096
|
||||
#define PBLKSIZ 1024
|
||||
#define PAIRMAX 1008 /* arbitrary on PBLKSIZ-N */
|
||||
#define SPLTMAX 10 /* maximum allowed splits */
|
||||
/* for a single insertion */
|
||||
#define DIRFEXT ".dir"
|
||||
#define PAGFEXT ".pag"
|
||||
|
||||
typedef struct {
|
||||
int dirf; /* directory file descriptor */
|
||||
int pagf; /* page file descriptor */
|
||||
int flags; /* status/error flags, see below */
|
||||
long maxbno; /* size of dirfile in bits */
|
||||
long curbit; /* current bit number */
|
||||
long hmask; /* current hash mask */
|
||||
long blkptr; /* current block for nextkey */
|
||||
int keyptr; /* current key for nextkey */
|
||||
long blkno; /* current page to read/write */
|
||||
long pagbno; /* current page in pagbuf */
|
||||
char pagbuf[PBLKSIZ]; /* page file block buffer */
|
||||
long dirbno; /* current block in dirbuf */
|
||||
char dirbuf[DBLKSIZ]; /* directory file block buffer */
|
||||
} DBM;
|
||||
|
||||
#define DBM_RDONLY 0x1 /* data base open read-only */
|
||||
#define DBM_IOERR 0x2 /* data base I/O error */
|
||||
|
||||
/*
|
||||
* utility macros
|
||||
*/
|
||||
#define sdbm_rdonly(db) ((db)->flags & DBM_RDONLY)
|
||||
#define sdbm_error(db) ((db)->flags & DBM_IOERR)
|
||||
|
||||
#define sdbm_clearerr(db) ((db)->flags &= ~DBM_IOERR) /* ouch */
|
||||
|
||||
#define sdbm_dirfno(db) ((db)->dirf)
|
||||
#define sdbm_pagfno(db) ((db)->pagf)
|
||||
|
||||
typedef struct {
|
||||
char *dptr;
|
||||
int dsize;
|
||||
} datum;
|
||||
|
||||
extern datum nullitem;
|
||||
|
||||
#if defined(__STDC__) || defined(MSDOS)
|
||||
#define proto(p) p
|
||||
#else
|
||||
#define proto(p) ()
|
||||
#endif
|
||||
|
||||
/*
|
||||
* flags to sdbm_store
|
||||
*/
|
||||
#define DBM_INSERT 0
|
||||
#define DBM_REPLACE 1
|
||||
|
||||
/*
|
||||
* ndbm interface
|
||||
*/
|
||||
extern DBM *sdbm_open proto((char *, int, int));
|
||||
extern void sdbm_close proto((DBM *));
|
||||
extern datum sdbm_fetch proto((DBM *, datum));
|
||||
extern int sdbm_delete proto((DBM *, datum));
|
||||
extern int sdbm_store proto((DBM *, datum, datum, int));
|
||||
extern datum sdbm_firstkey proto((DBM *));
|
||||
extern datum sdbm_nextkey proto((DBM *));
|
||||
|
||||
/*
|
||||
* other
|
||||
*/
|
||||
extern DBM *sdbm_prep proto((char *, char *, int, int));
|
||||
extern long sdbm_hash proto((char *, int));
|
||||
|
||||
#endif /* _SDBM_H_ */
|
|
@ -1,4 +1,8 @@
|
|||
MANIFEST
|
||||
addrinfo.h
|
||||
depend
|
||||
extconf.rb
|
||||
getaddrinfo.c
|
||||
getnameinfo.c
|
||||
sockport.h
|
||||
socket.c
|
||||
|
|
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef ADDR_INFO_H
|
||||
#define ADDR_INFO_H
|
||||
#ifndef HAVE_GETADDRINFO
|
||||
|
||||
/* special compatibility hack */
|
||||
#undef EAI_ADDRFAMILY
|
||||
#undef EAI_AGAIN
|
||||
#undef EAI_BADFLAGS
|
||||
#undef EAI_FAIL
|
||||
#undef EAI_FAMILY
|
||||
#undef EAI_MEMORY
|
||||
#undef EAI_NODATA
|
||||
#undef EAI_NONAME
|
||||
#undef EAI_SERVICE
|
||||
#undef EAI_SOCKTYPE
|
||||
#undef EAI_SYSTEM
|
||||
#undef EAI_BADHINTS
|
||||
#undef EAI_PROTOCOL
|
||||
#undef EAI_MAX
|
||||
|
||||
#undef AI_PASSIVE
|
||||
#undef AI_CANONNAME
|
||||
#undef AI_NUMERICHOST
|
||||
#undef AI_ALL
|
||||
#undef AI_ADDRCONFIG
|
||||
#undef AI_V4MAPPED
|
||||
#undef AI_DEFAULT
|
||||
|
||||
#undef NI_NOFQDN
|
||||
#undef NI_NUMERICHOST
|
||||
#undef NI_NAMEREQD
|
||||
#undef NI_NUMERICSERV
|
||||
#undef NI_DGRAM
|
||||
|
||||
#define addrinfo addrinfo__compat
|
||||
#define getaddrinfo getaddrinfo__compat
|
||||
#define getnameinfo getnameinfo__compat
|
||||
#define freehostent freehostent__compat
|
||||
#define freeaddrinfo freeaddrinfo__compat
|
||||
|
||||
#ifndef __P
|
||||
# ifdef HAVE_PROTOTYPES
|
||||
# define __P(args) args
|
||||
# else
|
||||
# define __P(args) ()
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* special compatibility hack -- end*/
|
||||
|
||||
|
||||
/*
|
||||
* Error return codes from getaddrinfo()
|
||||
*/
|
||||
#define EAI_ADDRFAMILY 1 /* address family for hostname not supported */
|
||||
#define EAI_AGAIN 2 /* temporary failure in name resolution */
|
||||
#define EAI_BADFLAGS 3 /* invalid value for ai_flags */
|
||||
#define EAI_FAIL 4 /* non-recoverable failure in name resolution */
|
||||
#define EAI_FAMILY 5 /* ai_family not supported */
|
||||
#define EAI_MEMORY 6 /* memory allocation failure */
|
||||
#define EAI_NODATA 7 /* no address associated with hostname */
|
||||
#define EAI_NONAME 8 /* hostname nor servname provided, or not known */
|
||||
#define EAI_SERVICE 9 /* servname not supported for ai_socktype */
|
||||
#define EAI_SOCKTYPE 10 /* ai_socktype not supported */
|
||||
#define EAI_SYSTEM 11 /* system error returned in errno */
|
||||
#define EAI_BADHINTS 12
|
||||
#define EAI_PROTOCOL 13
|
||||
#define EAI_MAX 14
|
||||
|
||||
/*
|
||||
* Flag values for getaddrinfo()
|
||||
*/
|
||||
#define AI_PASSIVE 0x00000001 /* get address to use bind() */
|
||||
#define AI_CANONNAME 0x00000002 /* fill ai_canonname */
|
||||
#define AI_NUMERICHOST 0x00000004 /* prevent name resolution */
|
||||
/* valid flags for addrinfo */
|
||||
#define AI_MASK (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST)
|
||||
|
||||
#define AI_ALL 0x00000100 /* IPv6 and IPv4-mapped (with AI_V4MAPPED) */
|
||||
#define AI_V4MAPPED_CFG 0x00000200 /* accept IPv4-mapped if kernel supports */
|
||||
#define AI_ADDRCONFIG 0x00000400 /* only if any address is assigned */
|
||||
#define AI_V4MAPPED 0x00000800 /* accept IPv4-mapped IPv6 address */
|
||||
/* special recommended flags for getipnodebyname */
|
||||
#define AI_DEFAULT (AI_V4MAPPED_CFG | AI_ADDRCONFIG)
|
||||
|
||||
/*
|
||||
* Constants for getnameinfo()
|
||||
*/
|
||||
#define NI_MAXHOST 1025
|
||||
#define NI_MAXSERV 32
|
||||
|
||||
/*
|
||||
* Flag values for getnameinfo()
|
||||
*/
|
||||
#define NI_NOFQDN 0x00000001
|
||||
#define NI_NUMERICHOST 0x00000002
|
||||
#define NI_NAMEREQD 0x00000004
|
||||
#define NI_NUMERICSERV 0x00000008
|
||||
#define NI_DGRAM 0x00000010
|
||||
|
||||
#ifdef NT
|
||||
#define IN_EXPERIMENTAL(x) 0
|
||||
#define IN_LOOPBACKNET 0
|
||||
#endif
|
||||
|
||||
struct addrinfo {
|
||||
int ai_flags; /* AI_PASSIVE, AI_CANONNAME */
|
||||
int ai_family; /* PF_xxx */
|
||||
int ai_socktype; /* SOCK_xxx */
|
||||
int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
|
||||
size_t ai_addrlen; /* length of ai_addr */
|
||||
char *ai_canonname; /* canonical name for hostname */
|
||||
struct sockaddr *ai_addr; /* binary address */
|
||||
struct addrinfo *ai_next; /* next structure in linked list */
|
||||
};
|
||||
|
||||
extern int getaddrinfo __P((
|
||||
const char *hostname, const char *servname,
|
||||
const struct addrinfo *hints,
|
||||
struct addrinfo **res));
|
||||
|
||||
extern int getnameinfo __P((
|
||||
const struct sockaddr *sa,
|
||||
size_t salen,
|
||||
char *host,
|
||||
size_t hostlen,
|
||||
char *serv,
|
||||
size_t servlen,
|
||||
int flags));
|
||||
|
||||
extern void freehostent __P((struct hostent *));
|
||||
extern void freeaddrent __P((struct addrinfo *));
|
||||
extern char *gai_strerror __P((int));
|
||||
|
||||
/* In case there is no definition of offsetof() provided - though any proper
|
||||
Standard C system should have one. */
|
||||
|
||||
#ifndef offsetof
|
||||
#define offsetof(p_type,field) ((size_t)&(((p_type *)0)->field))
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -1 +1,3 @@
|
|||
socket.o : socket.c $(hdrdir)/ruby.h $(hdrdir)/config.h $(hdrdir)/defines.h $(hdrdir)/rubyio.h $(hdrdir)/rubysig.h
|
||||
socket.o : socket.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h $(hdrdir)/rubyio.h $(hdrdir)/rubysig.h sockport.h
|
||||
getnameinfo.o: getnameinfo.c $(topdir)/config.h addrinfo.h sockport.h
|
||||
getaddrinfo.o: getaddrinfo.c $(topdir)/config.h addrinfo.h sockport.h
|
||||
|
|
|
@ -1,27 +1,276 @@
|
|||
require 'mkmf'
|
||||
$LDFLAGS = "-L/usr/local/lib" if File.directory?("/usr/local/lib")
|
||||
$LDFLAGS += " -L/usr/local/lib" if File.directory?("/usr/local/lib")
|
||||
$CFLAGS += " -Dss_family=__ss_family -Dss_len=__ss_len"
|
||||
|
||||
case PLATFORM
|
||||
when /mswin32/
|
||||
test_func = "WSACleanup"
|
||||
have_library("wsock32", "WSACleanup")
|
||||
when /cygwin32/
|
||||
when /cygwin/
|
||||
$LDFLAGS << " -L/usr/lib" if File.directory?("/usr/lib")
|
||||
$CFLAGS << " -I/usr/include"
|
||||
test_func = "socket"
|
||||
have_library("bind", "gethostbyaddr")
|
||||
when /beos/
|
||||
test_func = "socket"
|
||||
have_library("net", "socket")
|
||||
when /i386-os2_emx/
|
||||
test_func = "socket"
|
||||
have_library("socket", "socket")
|
||||
else
|
||||
test_func = "socket"
|
||||
have_library("nsl", "t_open")
|
||||
have_library("socket", "socket")
|
||||
end
|
||||
|
||||
$ipv6 = false
|
||||
if enable_config("ipv6", false)
|
||||
if try_link(<<EOF)
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
main()
|
||||
{
|
||||
socket(AF_INET6, SOCK_STREAM, 0);
|
||||
}
|
||||
EOF
|
||||
$CFLAGS+=" -DENABLE_IPV6"
|
||||
$ipv6 = true
|
||||
end
|
||||
end
|
||||
|
||||
$ipv6type = nil
|
||||
$ipv6lib = nil
|
||||
$ipv6libdir = nil
|
||||
if $ipv6
|
||||
if egrep_cpp("yes", <<EOF)
|
||||
#include <netinet/in.h>
|
||||
#ifdef IPV6_INRIA_VERSION
|
||||
yes
|
||||
#endif
|
||||
EOF
|
||||
$ipv6type = "inria"
|
||||
$CFLAGS="-DINET6 "+$CFLAGS
|
||||
elsif egrep_cpp("yes", <<EOF)
|
||||
#include <netinet/in.h>
|
||||
#ifdef __KAME__
|
||||
yes
|
||||
#endif
|
||||
EOF
|
||||
$ipv6type = "kame"
|
||||
$ipv6lib="inet6"
|
||||
$ipv6libdir="/usr/local/v6/lib"
|
||||
$CFLAGS="-DINET6 "+$CFLAGS
|
||||
elsif File.directory? "/usr/inet6"
|
||||
$ipv6type = "linux"
|
||||
$ipv6lib="inet6"
|
||||
$ipv6libdir="/usr/inet6/lib"
|
||||
$CFLAGS="-DINET6 -I/usr/inet6/include "+$CFLAGS
|
||||
elsif egrep_cpp("yes", <<EOF)
|
||||
#include <sys/param.h>
|
||||
#ifdef _TOSHIBA_INET6
|
||||
yes
|
||||
#endif
|
||||
EOF
|
||||
$ipv6type = "toshiba"
|
||||
$ipv6lib="inet6"
|
||||
$ipv6libdir="/usr/local/v6/lib"
|
||||
$CFLAGS="-DINET6 "+$CFLAGS
|
||||
elsif egrep_cpp("yes", <<EOF)
|
||||
#include </usr/local/v6/include/sys/v6config.h>
|
||||
#ifdef __V6D__
|
||||
yes
|
||||
#endif
|
||||
EOF
|
||||
$ipv6type = "v6d"
|
||||
$ipv6lib="v6"
|
||||
$ipv6libdir="/usr/local/v6/lib"
|
||||
$CFLAGS="-DINET6 -I/usr/local/v6/include "+$CFLAGS
|
||||
elsif egrep_cpp("yes", <<EOF)
|
||||
#include <sys/param.h>
|
||||
#ifdef _ZETA_MINAMI_INET6
|
||||
yes
|
||||
#endif
|
||||
EOF
|
||||
$ipv6type = "zeta"
|
||||
$ipv6lib="inet6"
|
||||
$ipv6libdir="/usr/local/v6/lib"
|
||||
$CFLAGS="-DINET6 "+$CFLAGS
|
||||
end
|
||||
|
||||
if $ipv6lib
|
||||
if File.directory? $ipv6libdir and File.exist? "#{$ipv6libdir}/lib#{$ipv6lib}.a"
|
||||
$LOCAL_LIBS = " -L#$ipv6libdir -l#$ipv6lib"
|
||||
else
|
||||
print <<EOS
|
||||
|
||||
Fatal: no #$ipv6lib library found. cannot continue.
|
||||
You need to fetch lib#{$ipv6lib}.a from appropriate
|
||||
ipv6 kit and compile beforehand.
|
||||
EOS
|
||||
exit
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if try_link(<<EOF)
|
||||
#include <sys/types.h>
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
int
|
||||
main()
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
|
||||
sin.sin_len;
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
$CFLAGS="-DHAVE_SIN_LEN "+$CFLAGS
|
||||
end
|
||||
|
||||
if try_link(<<EOF)
|
||||
#include <sys/types.h>
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
int
|
||||
main()
|
||||
{
|
||||
struct sockaddr sa;
|
||||
|
||||
sa.sa_len;
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
$CFLAGS="-DHAVE_SA_LEN "+$CFLAGS
|
||||
end
|
||||
|
||||
have_header("sys/sysctl.h")
|
||||
|
||||
$getaddr_info_ok = false
|
||||
if try_run(<<EOF)
|
||||
#include <sys/types.h>
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
main()
|
||||
{
|
||||
int passive, gaierr, inet4 = 0, inet6 = 0;
|
||||
struct addrinfo hints, *ai, *aitop;
|
||||
char straddr[INET6_ADDRSTRLEN], strport[16];
|
||||
|
||||
for (passive = 0; passive <= 1; passive++) {
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_flags = passive ? AI_PASSIVE : 0;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
if ((gaierr = getaddrinfo(NULL, "54321", &hints, &aitop)) != 0) {
|
||||
(void)gai_strerror(gaierr);
|
||||
goto bad;
|
||||
}
|
||||
for (ai = aitop; ai; ai = ai->ai_next) {
|
||||
if (ai->ai_addr == NULL ||
|
||||
ai->ai_addrlen == 0 ||
|
||||
getnameinfo(ai->ai_addr, ai->ai_addrlen,
|
||||
straddr, sizeof(straddr), strport, sizeof(strport),
|
||||
NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
|
||||
goto bad;
|
||||
}
|
||||
if (strcmp(strport, "54321") != 0) {
|
||||
goto bad;
|
||||
}
|
||||
switch (ai->ai_family) {
|
||||
case AF_INET:
|
||||
if (passive) {
|
||||
if (strcmp(straddr, "0.0.0.0") != 0) {
|
||||
goto bad;
|
||||
}
|
||||
} else {
|
||||
if (strcmp(straddr, "127.0.0.1") != 0) {
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
inet4++;
|
||||
break;
|
||||
case AF_INET6:
|
||||
if (passive) {
|
||||
if (strcmp(straddr, "::") != 0) {
|
||||
goto bad;
|
||||
}
|
||||
} else {
|
||||
if (strcmp(straddr, "::1") != 0) {
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
inet6++;
|
||||
break;
|
||||
case AF_UNSPEC:
|
||||
goto bad;
|
||||
break;
|
||||
default:
|
||||
/* another family support? */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (inet6 != 2 || inet4 != 2)
|
||||
goto bad;
|
||||
|
||||
if (aitop)
|
||||
freeaddrinfo(aitop);
|
||||
exit(0);
|
||||
|
||||
bad:
|
||||
if (aitop)
|
||||
freeaddrinfo(aitop);
|
||||
exit(1);
|
||||
}
|
||||
EOF
|
||||
$getaddr_info_ok = true
|
||||
end
|
||||
if $ipv6 and not $getaddr_info_ok
|
||||
print <<EOS
|
||||
|
||||
Fatal: --enable-ipv6 is specified, and your OS seems to support IPv6 feature.
|
||||
But your getaddrinfo() and getnameinfo() are appeared to be broken. Sorry,
|
||||
you cannot compile IPv6 socket classes with broken these functions.
|
||||
EOS
|
||||
exit
|
||||
end
|
||||
|
||||
|
||||
$objs = ["socket.#{$OBJEXT}"]
|
||||
|
||||
if $getaddr_info_ok and have_func("getaddrinfo") and have_func("getnameinfo")
|
||||
have_getaddrinfo = true
|
||||
end
|
||||
|
||||
if have_getaddrinfo
|
||||
$CFLAGS="-DHAVE_GETADDRINFO "+$CFLAGS
|
||||
else
|
||||
$CFLAGS="-I. "+$CFLAGS
|
||||
$objs += ["getaddrinfo.#{$OBJEXT}"]
|
||||
$objs += ["getnameinfo.#{$OBJEXT}"]
|
||||
have_func("inet_ntop") or have_func("inet_ntoa")
|
||||
have_func("inet_pton") or have_func("inet_aton")
|
||||
have_header("arpa/nameser.h")
|
||||
have_header("resolv.h")
|
||||
end
|
||||
|
||||
have_header("sys/un.h")
|
||||
|
||||
if have_func(test_func)
|
||||
have_func("inet_aton")
|
||||
have_func("hsterror")
|
||||
unless have_func("gethostname")
|
||||
have_func("uname")
|
||||
end
|
||||
if ENV["SOCKS_SERVER"] # test if SOCKSsocket needed
|
||||
if ENV["SOCKS_SERVER"] or enable_config("socks", false)
|
||||
if have_library("socks", "Rconnect")
|
||||
$CFLAGS="-DSOCKS"
|
||||
end
|
||||
|
|
|
@ -0,0 +1,676 @@
|
|||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator.
|
||||
*
|
||||
* Issues to be discussed:
|
||||
* - Thread safe-ness must be checked.
|
||||
* - Return values. There are nonstandard return values defined and used
|
||||
* in the source code. This is because RFC2133 is silent about which error
|
||||
* code must be returned for which situation.
|
||||
* - PF_UNSPEC case would be handled in getipnodebyname() with the AI_ALL flag.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifndef NT
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYSCTL_H
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
#ifndef NT
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#if defined(HAVE_ARPA_NAMESER_H)
|
||||
#include <arpa/nameser.h>
|
||||
#endif
|
||||
#include <netdb.h>
|
||||
#if defined(HAVE_RESOLV_H)
|
||||
#include <resolv.h>
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#include <io.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "addrinfo.h"
|
||||
#include "sockport.h"
|
||||
|
||||
#if defined(__KAME__) && defined(INET6)
|
||||
# define FAITH
|
||||
#endif
|
||||
|
||||
#define SUCCESS 0
|
||||
#define ANY 0
|
||||
#define YES 1
|
||||
#define NO 0
|
||||
|
||||
#ifdef FAITH
|
||||
static int translate = NO;
|
||||
static struct in6_addr faith_prefix = IN6ADDR_ANY_INIT;
|
||||
#endif
|
||||
|
||||
static const char in_addrany[] = { 0, 0, 0, 0 };
|
||||
static const char in6_addrany[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
static const char in_loopback[] = { 127, 0, 0, 1 };
|
||||
static const char in6_loopback[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
|
||||
};
|
||||
|
||||
struct sockinet {
|
||||
u_char si_len;
|
||||
u_char si_family;
|
||||
u_short si_port;
|
||||
};
|
||||
|
||||
static struct afd {
|
||||
int a_af;
|
||||
int a_addrlen;
|
||||
int a_socklen;
|
||||
int a_off;
|
||||
const char *a_addrany;
|
||||
const char *a_loopback;
|
||||
} afdl [] = {
|
||||
#ifdef INET6
|
||||
#define N_INET6 0
|
||||
{PF_INET6, sizeof(struct in6_addr),
|
||||
sizeof(struct sockaddr_in6),
|
||||
offsetof(struct sockaddr_in6, sin6_addr),
|
||||
in6_addrany, in6_loopback},
|
||||
#define N_INET 1
|
||||
#else
|
||||
#define N_INET 0
|
||||
#endif
|
||||
{PF_INET, sizeof(struct in_addr),
|
||||
sizeof(struct sockaddr_in),
|
||||
offsetof(struct sockaddr_in, sin_addr),
|
||||
in_addrany, in_loopback},
|
||||
{0, 0, 0, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
#ifdef INET6
|
||||
#define PTON_MAX 16
|
||||
#else
|
||||
#define PTON_MAX 4
|
||||
#endif
|
||||
|
||||
|
||||
static int get_name __P((const char *, struct afd *,
|
||||
struct addrinfo **, char *, struct addrinfo *,
|
||||
int));
|
||||
static int get_addr __P((const char *, int, struct addrinfo **,
|
||||
struct addrinfo *, int));
|
||||
static int str_isnumber __P((const char *));
|
||||
|
||||
static char *ai_errlist[] = {
|
||||
"success.",
|
||||
"address family for hostname not supported.", /* EAI_ADDRFAMILY */
|
||||
"temporary failure in name resolution.", /* EAI_AGAIN */
|
||||
"invalid value for ai_flags.", /* EAI_BADFLAGS */
|
||||
"non-recoverable failure in name resolution.", /* EAI_FAIL */
|
||||
"ai_family not supported.", /* EAI_FAMILY */
|
||||
"memory allocation failure.", /* EAI_MEMORY */
|
||||
"no address associated with hostname.", /* EAI_NODATA */
|
||||
"hostname nor servname provided, or not known.",/* EAI_NONAME */
|
||||
"servname not supported for ai_socktype.", /* EAI_SERVICE */
|
||||
"ai_socktype not supported.", /* EAI_SOCKTYPE */
|
||||
"system error returned in errno.", /* EAI_SYSTEM */
|
||||
"invalid value for hints.", /* EAI_BADHINTS */
|
||||
"resolved protocol is unknown.", /* EAI_PROTOCOL */
|
||||
"unknown error.", /* EAI_MAX */
|
||||
};
|
||||
|
||||
#define GET_CANONNAME(ai, str) \
|
||||
if (pai->ai_flags & AI_CANONNAME) {\
|
||||
if (((ai)->ai_canonname = (char *)malloc(strlen(str) + 1)) != NULL) {\
|
||||
strcpy((ai)->ai_canonname, (str));\
|
||||
} else {\
|
||||
error = EAI_MEMORY;\
|
||||
goto free;\
|
||||
}\
|
||||
}
|
||||
|
||||
#define GET_AI(ai, afd, addr, port) {\
|
||||
char *p;\
|
||||
if (((ai) = (struct addrinfo *)malloc(sizeof(struct addrinfo) +\
|
||||
((afd)->a_socklen)))\
|
||||
== NULL) {\
|
||||
error = EAI_MEMORY;\
|
||||
goto free;\
|
||||
}\
|
||||
memcpy(ai, pai, sizeof(struct addrinfo));\
|
||||
(ai)->ai_addr = (struct sockaddr *)((ai) + 1);\
|
||||
memset((ai)->ai_addr, 0, (afd)->a_socklen);\
|
||||
SET_SA_LEN((ai)->ai_addr, (ai)->ai_addrlen = (afd)->a_socklen);\
|
||||
(ai)->ai_addr->sa_family = (ai)->ai_family = (afd)->a_af;\
|
||||
((struct sockinet *)(ai)->ai_addr)->si_port = port;\
|
||||
p = (char *)((ai)->ai_addr);\
|
||||
memcpy(p + (afd)->a_off, (addr), (afd)->a_addrlen);\
|
||||
}
|
||||
|
||||
#define ERR(err) { error = (err); goto bad; }
|
||||
|
||||
char *
|
||||
gai_strerror(ecode)
|
||||
int ecode;
|
||||
{
|
||||
if (ecode < 0 || ecode > EAI_MAX)
|
||||
ecode = EAI_MAX;
|
||||
return ai_errlist[ecode];
|
||||
}
|
||||
|
||||
void
|
||||
freeaddrinfo(ai)
|
||||
struct addrinfo *ai;
|
||||
{
|
||||
struct addrinfo *next;
|
||||
|
||||
do {
|
||||
next = ai->ai_next;
|
||||
if (ai->ai_canonname)
|
||||
free(ai->ai_canonname);
|
||||
/* no need to free(ai->ai_addr) */
|
||||
free(ai);
|
||||
} while ((ai = next) != NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
str_isnumber(p)
|
||||
const char *p;
|
||||
{
|
||||
char *q = (char *)p;
|
||||
while (*q) {
|
||||
if (! isdigit(*q))
|
||||
return NO;
|
||||
q++;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
#ifndef HAVE_INET_PTON
|
||||
|
||||
static int
|
||||
inet_pton(af, hostname, pton)
|
||||
int af;
|
||||
const char *hostname;
|
||||
void *pton;
|
||||
{
|
||||
struct in_addr in;
|
||||
|
||||
#ifdef HAVE_INET_ATON
|
||||
if (!inet_aton(hostname, &in))
|
||||
return 0;
|
||||
#else
|
||||
int d1, d2, d3, d4;
|
||||
char ch;
|
||||
|
||||
if (sscanf(hostname, "%d.%d.%d.%d%c", &d1, &d2, &d3, &d4, &ch) == 4 &&
|
||||
0 <= d1 && d1 <= 255 && 0 <= d2 && d2 <= 255 &&
|
||||
0 <= d3 && d3 <= 255 && 0 <= d4 && d4 <= 255) {
|
||||
in.s_addr = htonl(
|
||||
((long) d1 << 24) | ((long) d2 << 16) |
|
||||
((long) d3 << 8) | ((long) d4 << 0));
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
memcpy(pton, &in, sizeof(in));
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
getaddrinfo(hostname, servname, hints, res)
|
||||
const char *hostname, *servname;
|
||||
const struct addrinfo *hints;
|
||||
struct addrinfo **res;
|
||||
{
|
||||
struct addrinfo sentinel;
|
||||
struct addrinfo *top = NULL;
|
||||
struct addrinfo *cur;
|
||||
int i, error = 0;
|
||||
char pton[PTON_MAX];
|
||||
struct addrinfo ai;
|
||||
struct addrinfo *pai;
|
||||
u_short port;
|
||||
|
||||
#ifdef FAITH
|
||||
static int firsttime = 1;
|
||||
|
||||
if (firsttime) {
|
||||
/* translator hack */
|
||||
{
|
||||
char *q = getenv("GAI");
|
||||
if (q && inet_pton(AF_INET6, q, &faith_prefix) == 1)
|
||||
translate = YES;
|
||||
}
|
||||
firsttime = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* initialize file static vars */
|
||||
sentinel.ai_next = NULL;
|
||||
cur = &sentinel;
|
||||
pai = &ai;
|
||||
pai->ai_flags = 0;
|
||||
pai->ai_family = PF_UNSPEC;
|
||||
pai->ai_socktype = ANY;
|
||||
pai->ai_protocol = ANY;
|
||||
pai->ai_addrlen = 0;
|
||||
pai->ai_canonname = NULL;
|
||||
pai->ai_addr = NULL;
|
||||
pai->ai_next = NULL;
|
||||
port = ANY;
|
||||
|
||||
if (hostname == NULL && servname == NULL)
|
||||
return EAI_NONAME;
|
||||
if (hints) {
|
||||
/* error check for hints */
|
||||
if (hints->ai_addrlen || hints->ai_canonname ||
|
||||
hints->ai_addr || hints->ai_next)
|
||||
ERR(EAI_BADHINTS); /* xxx */
|
||||
if (hints->ai_flags & ~AI_MASK)
|
||||
ERR(EAI_BADFLAGS);
|
||||
switch (hints->ai_family) {
|
||||
case PF_UNSPEC:
|
||||
case PF_INET:
|
||||
#ifdef INET6
|
||||
case PF_INET6:
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
ERR(EAI_FAMILY);
|
||||
}
|
||||
memcpy(pai, hints, sizeof(*pai));
|
||||
switch (pai->ai_socktype) {
|
||||
case ANY:
|
||||
switch (pai->ai_protocol) {
|
||||
case ANY:
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
pai->ai_socktype = SOCK_DGRAM;
|
||||
break;
|
||||
case IPPROTO_TCP:
|
||||
pai->ai_socktype = SOCK_STREAM;
|
||||
break;
|
||||
default:
|
||||
pai->ai_socktype = SOCK_RAW;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SOCK_RAW:
|
||||
break;
|
||||
case SOCK_DGRAM:
|
||||
if (pai->ai_protocol != IPPROTO_UDP &&
|
||||
pai->ai_protocol != ANY)
|
||||
ERR(EAI_BADHINTS); /*xxx*/
|
||||
pai->ai_protocol = IPPROTO_UDP;
|
||||
break;
|
||||
case SOCK_STREAM:
|
||||
if (pai->ai_protocol != IPPROTO_TCP &&
|
||||
pai->ai_protocol != ANY)
|
||||
ERR(EAI_BADHINTS); /*xxx*/
|
||||
pai->ai_protocol = IPPROTO_TCP;
|
||||
break;
|
||||
default:
|
||||
ERR(EAI_SOCKTYPE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* service port
|
||||
*/
|
||||
if (servname) {
|
||||
if (str_isnumber(servname)) {
|
||||
if (pai->ai_socktype == ANY) {
|
||||
/* caller accept *ANY* socktype */
|
||||
pai->ai_socktype = SOCK_DGRAM;
|
||||
pai->ai_protocol = IPPROTO_UDP;
|
||||
}
|
||||
port = htons((unsigned short)atoi(servname));
|
||||
} else {
|
||||
struct servent *sp;
|
||||
char *proto;
|
||||
|
||||
proto = NULL;
|
||||
switch (pai->ai_socktype) {
|
||||
case ANY:
|
||||
proto = NULL;
|
||||
break;
|
||||
case SOCK_DGRAM:
|
||||
proto = "udp";
|
||||
break;
|
||||
case SOCK_STREAM:
|
||||
proto = "tcp";
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "panic!\n");
|
||||
break;
|
||||
}
|
||||
if ((sp = getservbyname(servname, proto)) == NULL)
|
||||
ERR(EAI_SERVICE);
|
||||
port = sp->s_port;
|
||||
if (pai->ai_socktype == ANY)
|
||||
if (strcmp(sp->s_proto, "udp") == 0) {
|
||||
pai->ai_socktype = SOCK_DGRAM;
|
||||
pai->ai_protocol = IPPROTO_UDP;
|
||||
} else if (strcmp(sp->s_proto, "tcp") == 0) {
|
||||
pai->ai_socktype = SOCK_STREAM;
|
||||
pai->ai_protocol = IPPROTO_TCP;
|
||||
} else
|
||||
ERR(EAI_PROTOCOL); /*xxx*/
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* hostname == NULL.
|
||||
* passive socket -> anyaddr (0.0.0.0 or ::)
|
||||
* non-passive socket -> localhost (127.0.0.1 or ::1)
|
||||
*/
|
||||
if (hostname == NULL) {
|
||||
struct afd *afd;
|
||||
int s;
|
||||
|
||||
for (afd = &afdl[0]; afd->a_af; afd++) {
|
||||
if (!(pai->ai_family == PF_UNSPEC
|
||||
|| pai->ai_family == afd->a_af)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* filter out AFs that are not supported by the kernel
|
||||
* XXX errno?
|
||||
*/
|
||||
s = socket(afd->a_af, SOCK_DGRAM, 0);
|
||||
if (s < 0)
|
||||
continue;
|
||||
close(s);
|
||||
|
||||
if (pai->ai_flags & AI_PASSIVE) {
|
||||
GET_AI(cur->ai_next, afd, afd->a_addrany, port);
|
||||
/* xxx meaningless?
|
||||
* GET_CANONNAME(cur->ai_next, "anyaddr");
|
||||
*/
|
||||
} else {
|
||||
GET_AI(cur->ai_next, afd, afd->a_loopback,
|
||||
port);
|
||||
/* xxx meaningless?
|
||||
* GET_CANONNAME(cur->ai_next, "localhost");
|
||||
*/
|
||||
}
|
||||
cur = cur->ai_next;
|
||||
}
|
||||
top = sentinel.ai_next;
|
||||
if (top)
|
||||
goto good;
|
||||
else
|
||||
ERR(EAI_FAMILY);
|
||||
}
|
||||
|
||||
/* hostname as numeric name */
|
||||
for (i = 0; afdl[i].a_af; i++) {
|
||||
if (inet_pton(afdl[i].a_af, hostname, pton)) {
|
||||
u_long v4a;
|
||||
#ifdef INET6
|
||||
u_char pfx;
|
||||
#endif
|
||||
|
||||
switch (afdl[i].a_af) {
|
||||
case AF_INET:
|
||||
v4a = ((struct in_addr *)pton)->s_addr;
|
||||
if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
|
||||
pai->ai_flags &= ~AI_CANONNAME;
|
||||
v4a >>= IN_CLASSA_NSHIFT;
|
||||
if (v4a == 0 || v4a == IN_LOOPBACKNET)
|
||||
pai->ai_flags &= ~AI_CANONNAME;
|
||||
break;
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
pfx = ((struct in6_addr *)pton)->s6_addr8[0];
|
||||
if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
|
||||
pai->ai_flags &= ~AI_CANONNAME;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (pai->ai_family == afdl[i].a_af ||
|
||||
pai->ai_family == PF_UNSPEC) {
|
||||
if (! (pai->ai_flags & AI_CANONNAME)) {
|
||||
GET_AI(top, &afdl[i], pton, port);
|
||||
goto good;
|
||||
}
|
||||
/*
|
||||
* if AI_CANONNAME and if reverse lookup
|
||||
* fail, return ai anyway to pacify
|
||||
* calling application.
|
||||
*
|
||||
* XXX getaddrinfo() is a name->address
|
||||
* translation function, and it looks strange
|
||||
* that we do addr->name translation here.
|
||||
*/
|
||||
get_name(pton, &afdl[i], &top, pton, pai, port);
|
||||
goto good;
|
||||
} else
|
||||
ERR(EAI_FAMILY); /*xxx*/
|
||||
}
|
||||
}
|
||||
|
||||
if (pai->ai_flags & AI_NUMERICHOST)
|
||||
ERR(EAI_NONAME);
|
||||
|
||||
/* hostname as alphabetical name */
|
||||
error = get_addr(hostname, pai->ai_family, &top, pai, port);
|
||||
if (error == 0) {
|
||||
if (top) {
|
||||
good:
|
||||
*res = top;
|
||||
return SUCCESS;
|
||||
} else
|
||||
error = EAI_FAIL;
|
||||
}
|
||||
free:
|
||||
if (top)
|
||||
freeaddrinfo(top);
|
||||
bad:
|
||||
*res = NULL;
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
get_name(addr, afd, res, numaddr, pai, port0)
|
||||
const char *addr;
|
||||
struct afd *afd;
|
||||
struct addrinfo **res;
|
||||
char *numaddr;
|
||||
struct addrinfo *pai;
|
||||
int port0;
|
||||
{
|
||||
u_short port = port0 & 0xffff;
|
||||
struct hostent *hp;
|
||||
struct addrinfo *cur;
|
||||
int error = 0;
|
||||
#ifdef INET6
|
||||
int h_error;
|
||||
#endif
|
||||
|
||||
#ifdef INET6
|
||||
hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
|
||||
#else
|
||||
hp = gethostbyaddr(addr, afd->a_addrlen, AF_INET);
|
||||
#endif
|
||||
if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
|
||||
GET_AI(cur, afd, hp->h_addr_list[0], port);
|
||||
GET_CANONNAME(cur, hp->h_name);
|
||||
} else
|
||||
GET_AI(cur, afd, numaddr, port);
|
||||
|
||||
#ifdef INET6
|
||||
if (hp)
|
||||
freehostent(hp);
|
||||
#endif
|
||||
*res = cur;
|
||||
return SUCCESS;
|
||||
free:
|
||||
if (cur)
|
||||
freeaddrinfo(cur);
|
||||
#ifdef INET6
|
||||
if (hp)
|
||||
freehostent(hp);
|
||||
#endif
|
||||
/* bad: */
|
||||
*res = NULL;
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
get_addr(hostname, af, res, pai, port0)
|
||||
const char *hostname;
|
||||
int af;
|
||||
struct addrinfo **res;
|
||||
struct addrinfo *pai;
|
||||
int port0;
|
||||
{
|
||||
u_short port = port0 & 0xffff;
|
||||
struct addrinfo sentinel;
|
||||
struct hostent *hp;
|
||||
struct addrinfo *top, *cur;
|
||||
struct afd *afd;
|
||||
int i, error = 0, h_error;
|
||||
char *ap;
|
||||
#ifndef INET6
|
||||
#ifndef NT
|
||||
extern int h_errno;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
top = NULL;
|
||||
sentinel.ai_next = NULL;
|
||||
cur = &sentinel;
|
||||
#ifdef INET6
|
||||
if (af == AF_UNSPEC) {
|
||||
hp = getipnodebyname(hostname, AF_INET6,
|
||||
AI_ADDRCONFIG|AI_ALL|AI_V4MAPPED, &h_error);
|
||||
} else
|
||||
hp = getipnodebyname(hostname, af, AI_ADDRCONFIG, &h_error);
|
||||
#else
|
||||
hp = gethostbyname(hostname);
|
||||
h_error = h_errno;
|
||||
#endif
|
||||
if (hp == NULL) {
|
||||
switch (h_error) {
|
||||
case HOST_NOT_FOUND:
|
||||
case NO_DATA:
|
||||
error = EAI_NODATA;
|
||||
break;
|
||||
case TRY_AGAIN:
|
||||
error = EAI_AGAIN;
|
||||
break;
|
||||
case NO_RECOVERY:
|
||||
default:
|
||||
error = EAI_FAIL;
|
||||
break;
|
||||
}
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if ((hp->h_name == NULL) || (hp->h_name[0] == 0) ||
|
||||
(hp->h_addr_list[0] == NULL))
|
||||
ERR(EAI_FAIL);
|
||||
|
||||
for (i = 0; (ap = hp->h_addr_list[i]) != NULL; i++) {
|
||||
switch (af) {
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
afd = &afdl[N_INET6];
|
||||
break;
|
||||
#endif
|
||||
#ifndef INET6
|
||||
default: /* AF_UNSPEC */
|
||||
#endif
|
||||
case AF_INET:
|
||||
afd = &afdl[N_INET];
|
||||
break;
|
||||
#ifdef INET6
|
||||
default: /* AF_UNSPEC */
|
||||
if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) {
|
||||
ap += sizeof(struct in6_addr) -
|
||||
sizeof(struct in_addr);
|
||||
afd = &afdl[N_INET];
|
||||
} else
|
||||
afd = &afdl[N_INET6];
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
#ifdef FAITH
|
||||
if (translate && afd->a_af == AF_INET) {
|
||||
struct in6_addr *in6;
|
||||
|
||||
GET_AI(cur->ai_next, &afdl[N_INET6], ap, port);
|
||||
in6 = &((struct sockaddr_in6 *)cur->ai_next->ai_addr)->sin6_addr;
|
||||
memcpy(&in6->s6_addr32[0], &faith_prefix,
|
||||
sizeof(struct in6_addr) - sizeof(struct in_addr));
|
||||
memcpy(&in6->s6_addr32[3], ap, sizeof(struct in_addr));
|
||||
} else
|
||||
#endif /* FAITH */
|
||||
GET_AI(cur->ai_next, afd, ap, port);
|
||||
if (cur == &sentinel) {
|
||||
top = cur->ai_next;
|
||||
GET_CANONNAME(top, hp->h_name);
|
||||
}
|
||||
cur = cur->ai_next;
|
||||
}
|
||||
#ifdef INET6
|
||||
freehostent(hp);
|
||||
#endif
|
||||
*res = top;
|
||||
return SUCCESS;
|
||||
free:
|
||||
if (top)
|
||||
freeaddrinfo(top);
|
||||
#ifdef INET6
|
||||
if (hp)
|
||||
freehostent(hp);
|
||||
#endif
|
||||
bad:
|
||||
*res = NULL;
|
||||
return error;
|
||||
}
|
|
@ -0,0 +1,250 @@
|
|||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Issues to be discussed:
|
||||
* - Thread safe-ness must be checked
|
||||
* - Return values. There seems to be no standard for return value (RFC2133)
|
||||
* but INRIA implementation returns EAI_xxx defined for getaddrinfo().
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifndef NT
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#if defined(HAVE_ARPA_NAMESER_H)
|
||||
#include <arpa/nameser.h>
|
||||
#endif
|
||||
#include <netdb.h>
|
||||
#if defined(HAVE_RESOLV_H)
|
||||
#include <resolv.h>
|
||||
#endif
|
||||
#endif
|
||||
#ifdef NT
|
||||
#include <winsock2.h>
|
||||
#include <stdio.h>
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "addrinfo.h"
|
||||
#include "sockport.h"
|
||||
|
||||
#define SUCCESS 0
|
||||
#define ANY 0
|
||||
#define YES 1
|
||||
#define NO 0
|
||||
|
||||
struct sockinet {
|
||||
u_char si_len;
|
||||
u_char si_family;
|
||||
u_short si_port;
|
||||
};
|
||||
|
||||
static struct afd {
|
||||
int a_af;
|
||||
int a_addrlen;
|
||||
int a_socklen;
|
||||
int a_off;
|
||||
} afdl [] = {
|
||||
#ifdef INET6
|
||||
#define N_INET6 0
|
||||
{PF_INET6, sizeof(struct in6_addr),
|
||||
sizeof(struct sockaddr_in6),
|
||||
offsetof(struct sockaddr_in6, sin6_addr)},
|
||||
#define N_INET 1
|
||||
#else
|
||||
#define N_INET 0
|
||||
#endif
|
||||
{PF_INET, sizeof(struct in_addr),
|
||||
sizeof(struct sockaddr_in),
|
||||
offsetof(struct sockaddr_in, sin_addr)},
|
||||
{0, 0, 0, 0},
|
||||
};
|
||||
|
||||
#define ENI_NOSOCKET 0
|
||||
#define ENI_NOSERVNAME 1
|
||||
#define ENI_NOHOSTNAME 2
|
||||
#define ENI_MEMORY 3
|
||||
#define ENI_SYSTEM 4
|
||||
#define ENI_FAMILY 5
|
||||
#define ENI_SALEN 6
|
||||
|
||||
#ifndef HAVE_INET_NTOP
|
||||
static const char *
|
||||
inet_ntop(af, addr, numaddr, numaddr_len)
|
||||
int af;
|
||||
const void *addr;
|
||||
char *numaddr;
|
||||
size_t numaddr_len;
|
||||
{
|
||||
#ifdef HAVE_INET_NTOA
|
||||
struct in_addr in;
|
||||
memcpy(&in.s_addr, addr, sizeof(in.s_addr));
|
||||
snprintf(numaddr, numaddr_len, "%s", inet_ntoa(in));
|
||||
#else
|
||||
unsigned long x = ntohl(*(unsigned long*)addr);
|
||||
snprintf(numaddr, numaddr_len, "%d.%d.%d.%d",
|
||||
(int) (x>>24) & 0xff, (int) (x>>16) & 0xff,
|
||||
(int) (x>> 8) & 0xff, (int) (x>> 0) & 0xff);
|
||||
#endif
|
||||
return numaddr;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
|
||||
const struct sockaddr *sa;
|
||||
size_t salen;
|
||||
char *host;
|
||||
size_t hostlen;
|
||||
char *serv;
|
||||
size_t servlen;
|
||||
int flags;
|
||||
{
|
||||
struct afd *afd;
|
||||
struct servent *sp;
|
||||
struct hostent *hp;
|
||||
u_short port;
|
||||
int family, len, i;
|
||||
char *addr, *p;
|
||||
u_long v4a;
|
||||
#ifdef INET6
|
||||
u_char pfx;
|
||||
#endif
|
||||
int h_error;
|
||||
char numserv[512];
|
||||
char numaddr[512];
|
||||
#ifndef NT
|
||||
extern int h_errno;
|
||||
#endif
|
||||
|
||||
if (sa == NULL)
|
||||
return ENI_NOSOCKET;
|
||||
|
||||
len = SA_LEN(sa);
|
||||
if (len != salen) return ENI_SALEN;
|
||||
|
||||
family = sa->sa_family;
|
||||
for (i = 0; afdl[i].a_af; i++)
|
||||
if (afdl[i].a_af == family) {
|
||||
afd = &afdl[i];
|
||||
goto found;
|
||||
}
|
||||
return ENI_FAMILY;
|
||||
|
||||
found:
|
||||
if (len != afd->a_socklen) return ENI_SALEN;
|
||||
|
||||
port = ((struct sockinet *)sa)->si_port; /* network byte order */
|
||||
addr = (char *)sa + afd->a_off;
|
||||
|
||||
if (serv == NULL || servlen == 0) {
|
||||
/* what we should do? */
|
||||
} else if (flags & NI_NUMERICSERV) {
|
||||
snprintf(numserv, sizeof(numserv), "%d", ntohs(port));
|
||||
if (strlen(numserv) > servlen)
|
||||
return ENI_MEMORY;
|
||||
strcpy(serv, numserv);
|
||||
} else {
|
||||
sp = getservbyport(port, (flags & NI_DGRAM) ? "udp" : "tcp");
|
||||
if (sp) {
|
||||
if (strlen(sp->s_name) > servlen)
|
||||
return ENI_MEMORY;
|
||||
strcpy(serv, sp->s_name);
|
||||
} else
|
||||
return ENI_NOSERVNAME;
|
||||
}
|
||||
|
||||
switch (sa->sa_family) {
|
||||
case AF_INET:
|
||||
v4a = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
|
||||
if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
|
||||
flags |= NI_NUMERICHOST;
|
||||
v4a >>= IN_CLASSA_NSHIFT;
|
||||
if (v4a == 0 || v4a == IN_LOOPBACKNET)
|
||||
flags |= NI_NUMERICHOST;
|
||||
break;
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
pfx = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr8[0];
|
||||
if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
|
||||
flags |= NI_NUMERICHOST;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
if (host == NULL || hostlen == 0) {
|
||||
/* what should we do? */
|
||||
} else if (flags & NI_NUMERICHOST) {
|
||||
if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
|
||||
== NULL)
|
||||
return ENI_SYSTEM;
|
||||
if (strlen(numaddr) > hostlen)
|
||||
return ENI_MEMORY;
|
||||
strcpy(host, numaddr);
|
||||
} else {
|
||||
#ifdef INET6
|
||||
hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
|
||||
#else
|
||||
hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
|
||||
h_error = h_errno;
|
||||
#endif
|
||||
|
||||
if (hp) {
|
||||
if (flags & NI_NOFQDN) {
|
||||
p = strchr(hp->h_name, '.');
|
||||
if (p) *p = '\0';
|
||||
}
|
||||
if (strlen(hp->h_name) > hostlen) {
|
||||
#ifdef INET6
|
||||
freehostent(hp);
|
||||
#endif
|
||||
return ENI_MEMORY;
|
||||
}
|
||||
strcpy(host, hp->h_name);
|
||||
#ifdef INET6
|
||||
freehostent(hp);
|
||||
#endif
|
||||
} else {
|
||||
if (flags & NI_NAMEREQD)
|
||||
return ENI_NOHOSTNAME;
|
||||
if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
|
||||
== NULL)
|
||||
return ENI_NOHOSTNAME;
|
||||
if (strlen(numaddr) > hostlen)
|
||||
return ENI_MEMORY;
|
||||
strcpy(host, numaddr);
|
||||
}
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
1293
ext/socket/socket.c
1293
ext/socket/socket.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,43 @@
|
|||
/************************************************
|
||||
|
||||
sockport.h -
|
||||
|
||||
$Author$
|
||||
$Date$
|
||||
created at: Fri Apr 30 23:19:34 JST 1999
|
||||
|
||||
************************************************/
|
||||
|
||||
#ifndef SOCKPORT_H
|
||||
#define SOCKPORT_H
|
||||
|
||||
#ifndef SA_LEN
|
||||
# ifdef HAVE_SA_LEN
|
||||
# define SA_LEN(sa) (sa)->sa_len
|
||||
# else
|
||||
# ifdef INET6
|
||||
# define SA_LEN(sa) \
|
||||
(((sa)->sa_family == AF_INET6) ? sizeof(struct sockaddr_in6) \
|
||||
: sizeof(struct sockaddr))
|
||||
# else
|
||||
/* by tradition, sizeof(struct sockaddr) covers most of the sockaddrs */
|
||||
# define SA_LEN(sa) (sizeof(struct sockaddr))
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SA_LEN
|
||||
# define SET_SA_LEN(sa, len) (sa)->sa_len = (len)
|
||||
#else
|
||||
# define SET_SA_LEN(sa, len) (len)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SIN_LEN
|
||||
# define SIN_LEN(si) (si)->sin_len
|
||||
# define SET_SIN_LEN(si,len) (si)->sin_len = (len)
|
||||
#else
|
||||
# define SIN_LEN(si) sizeof(struct sockaddr_in)
|
||||
# define SET_SIN_LEN(si,len) (len)
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1 +1 @@
|
|||
tcltklib.o: tcltklib.c $(hdrdir)/ruby.h $(hdrdir)/config.h $(hdrdir)/defines.h
|
||||
tcltklib.o: tcltklib.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
|
||||
|
|
|
@ -7,79 +7,41 @@ have_library("socket", "socket")
|
|||
have_library("dl", "dlopen")
|
||||
have_library("m", "log")
|
||||
|
||||
$includes = []
|
||||
def search_header(include, *path)
|
||||
pwd = Dir.getwd
|
||||
begin
|
||||
for i in path.sort!.reverse!
|
||||
dir = Dir[i]
|
||||
for path in dir.sort!.reverse!
|
||||
next unless File.directory? path
|
||||
Dir.chdir path
|
||||
files = Dir[include]
|
||||
if files.size > 0
|
||||
unless $includes.include? path
|
||||
$includes << path
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
ensure
|
||||
Dir.chdir pwd
|
||||
dir_config("tk")
|
||||
dir_config("tcl")
|
||||
dir_config("X11")
|
||||
|
||||
tklib = with_config("tklib")
|
||||
tcllib = with_config("tcllib")
|
||||
|
||||
def find_tcl(tcllib)
|
||||
paths = ["/usr/local/lib", "/usr/pkg"]
|
||||
func = "Tcl_FindExecutable"
|
||||
if tcllib
|
||||
find_library(tcllib, func, *paths)
|
||||
else
|
||||
find_library("tcl", func, *paths) or
|
||||
find_library("tcl8.0", func, *paths) or
|
||||
find_library("tcl7.6", func, *paths)
|
||||
end
|
||||
end
|
||||
|
||||
search_header("tcl.h",
|
||||
"/usr/include/tcl{,8*,7*}",
|
||||
"/usr/include",
|
||||
"/usr/local/include/tcl{,8*,7*}",
|
||||
"/usr/local/include")
|
||||
search_header("tk.h",
|
||||
"/usr/include/tk{,8*,4*}",
|
||||
"/usr/include",
|
||||
"/usr/local/include/tk{,8*,4*}",
|
||||
"/usr/local/include")
|
||||
search_header("X11/Xlib.h",
|
||||
"/usr/include/X11*",
|
||||
"/usr/include",
|
||||
"/usr/openwin/include",
|
||||
"/usr/X11*/include")
|
||||
|
||||
$CFLAGS = $includes.collect{|path| "-I" + path}.join(" ")
|
||||
|
||||
$libraries = []
|
||||
def search_lib(file, func, *path)
|
||||
for i in path.reverse!
|
||||
dir = Dir[i]
|
||||
for path in dir.sort!.reverse!
|
||||
$LDFLAGS = $libraries.collect{|p| "-L" + p}.join(" ") + " -L" + path
|
||||
files = Dir[path+"/"+file]
|
||||
if files.size > 0
|
||||
for lib in files.sort!.reverse!
|
||||
lib = File::basename(lib)
|
||||
lib.sub!(/^lib/, '')
|
||||
lib.sub!(/\.(a|so)$/, '')
|
||||
if have_library(lib, func)
|
||||
unless $libraries.include? path
|
||||
$libraries << path
|
||||
end
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
def find_tk(tklib)
|
||||
paths = ["/usr/local/lib", "/usr/pkg"]
|
||||
func = "Tk_Init"
|
||||
if tklib
|
||||
find_library(tklib, func, *paths)
|
||||
else
|
||||
find_library("tk", func, *paths) or
|
||||
find_library("tk8.0", func, *paths) or
|
||||
find_library("tk4.2", func, *paths)
|
||||
end
|
||||
return false;
|
||||
end
|
||||
|
||||
if have_header("tcl.h") && have_header("tk.h") &&
|
||||
search_lib("libX11.{so,a}", "XOpenDisplay",
|
||||
"/usr/lib", "/usr/openwin/lib", "/usr/X11*/lib") &&
|
||||
search_lib("libtcl{8*,7*,}.{so,a}", "Tcl_FindExecutable",
|
||||
"/usr/lib", "/usr/local/lib") &&
|
||||
search_lib("libtk{8*,4*,}.{so,a}", "Tk_Init",
|
||||
"/usr/lib", "/usr/local/lib")
|
||||
$LDFLAGS = $libraries.collect{|path| "-L" + path}.join(" ")
|
||||
(/mswin32/ =~ RUBY_PLATFORM || find_library("X11", "XOpenDisplay",
|
||||
"/usr/X11/lib", "/usr/X11R6/lib", "/usr/openwin/lib")) &&
|
||||
find_tcl(tcllib) &&
|
||||
find_tk(tklib)
|
||||
create_makefile("tcltklib")
|
||||
end
|
||||
|
|
|
@ -4,22 +4,22 @@
|
|||
* Oct. 24, 1997 Y. Matsumoto
|
||||
*/
|
||||
|
||||
#include "ruby.h"
|
||||
#include "rubysig.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <tcl.h>
|
||||
#include <tk.h>
|
||||
#include "ruby.h"
|
||||
#include "rubysig.h"
|
||||
|
||||
#ifdef __MACOS__
|
||||
# include <tkMac.h>
|
||||
# include <Quickdraw.h>
|
||||
#endif
|
||||
|
||||
/* for rb_debug */
|
||||
/* for ruby_debug */
|
||||
|
||||
#define DUMP1(ARG1) if (rb_debug) { fprintf(stderr, "tcltklib: %s\n", ARG1);}
|
||||
#define DUMP2(ARG1, ARG2) if (rb_debug) { fprintf(stderr, "tcltklib: ");\
|
||||
#define DUMP1(ARG1) if (ruby_debug) { fprintf(stderr, "tcltklib: %s\n", ARG1);}
|
||||
#define DUMP2(ARG1, ARG2) if (ruby_debug) { fprintf(stderr, "tcltklib: ");\
|
||||
fprintf(stderr, ARG1, ARG2); fprintf(stderr, "\n"); }
|
||||
/*
|
||||
#define DUMP1(ARG1)
|
||||
|
@ -27,8 +27,10 @@ fprintf(stderr, ARG1, ARG2); fprintf(stderr, "\n"); }
|
|||
*/
|
||||
|
||||
/* for callback break & continue */
|
||||
VALUE eTkCallbackBreak;
|
||||
VALUE eTkCallbackContinue;
|
||||
static VALUE eTkCallbackBreak;
|
||||
static VALUE eTkCallbackContinue;
|
||||
|
||||
static VALUE ip_invoke_real _((int, VALUE*, VALUE));
|
||||
|
||||
/* from tkAppInit.c */
|
||||
|
||||
|
@ -42,51 +44,61 @@ int *tclDummyMathPtr = (int *) matherr;
|
|||
|
||||
/*---- module TclTkLib ----*/
|
||||
|
||||
struct invoke_queue {
|
||||
int argc;
|
||||
VALUE *argv;
|
||||
VALUE obj;
|
||||
int done;
|
||||
VALUE result;
|
||||
VALUE thread;
|
||||
struct invoke_queue *next;
|
||||
};
|
||||
|
||||
static struct invoke_queue *iqueue;
|
||||
static VALUE main_thread;
|
||||
|
||||
/* Tk_ThreadTimer */
|
||||
typedef struct {
|
||||
Tcl_TimerToken token;
|
||||
int flag;
|
||||
} Tk_TimerData;
|
||||
static Tcl_TimerToken timer_token;
|
||||
|
||||
/* timer callback */
|
||||
void _timer_for_tcl (ClientData clientData)
|
||||
static void
|
||||
_timer_for_tcl(clientData)
|
||||
ClientData clientData;
|
||||
{
|
||||
Tk_TimerData *timer = (Tk_TimerData*)clientData;
|
||||
struct invoke_queue *q, *tmp;
|
||||
VALUE thread;
|
||||
|
||||
Tk_DeleteTimerHandler(timer_token);
|
||||
timer_token = Tk_CreateTimerHandler(100, _timer_for_tcl,
|
||||
(ClientData)0);
|
||||
|
||||
timer->flag = 0;
|
||||
CHECK_INTS;
|
||||
#ifdef USE_THREAD
|
||||
if (!rb_thread_critical) rb_thread_schedule();
|
||||
#endif
|
||||
|
||||
timer->token = Tk_CreateTimerHandler(200, _timer_for_tcl,
|
||||
(ClientData)timer);
|
||||
timer->flag = 1;
|
||||
q = iqueue;
|
||||
while (q) {
|
||||
tmp = q;
|
||||
q = q->next;
|
||||
if (!tmp->done) {
|
||||
tmp->done = 1;
|
||||
tmp->result = ip_invoke_real(tmp->argc, tmp->argv, tmp->obj);
|
||||
thread = tmp->thread;
|
||||
tmp = tmp->next;
|
||||
rb_thread_run(thread);
|
||||
}
|
||||
}
|
||||
rb_thread_schedule();
|
||||
}
|
||||
|
||||
/* execute Tk_MainLoop */
|
||||
static VALUE
|
||||
lib_mainloop(VALUE self)
|
||||
lib_mainloop(self)
|
||||
VALUE self;
|
||||
{
|
||||
Tk_TimerData *timer;
|
||||
|
||||
timer = (Tk_TimerData *) ckalloc(sizeof(Tk_TimerData));
|
||||
timer->flag = 0;
|
||||
timer->token = Tk_CreateTimerHandler(200, _timer_for_tcl,
|
||||
(ClientData)timer);
|
||||
timer->flag = 1;
|
||||
|
||||
timer_token = Tk_CreateTimerHandler(100, _timer_for_tcl,
|
||||
(ClientData)0);
|
||||
DUMP1("start Tk_Mainloop");
|
||||
while (Tk_GetNumMainWindows() > 0) {
|
||||
Tcl_DoOneEvent(0);
|
||||
}
|
||||
Tk_MainLoop();
|
||||
DUMP1("stop Tk_Mainloop");
|
||||
|
||||
#ifdef USE_THREAD
|
||||
if (timer->flag) {
|
||||
Tk_DeleteTimerHandler(timer->token);
|
||||
}
|
||||
#endif
|
||||
Tk_DeleteTimerHandler(timer_token);
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
@ -99,7 +111,9 @@ struct tcltkip {
|
|||
|
||||
/* Tcl command `ruby' */
|
||||
static VALUE
|
||||
ip_eval_rescue(VALUE *failed, VALUE einfo)
|
||||
ip_eval_rescue(failed, einfo)
|
||||
VALUE *failed;
|
||||
VALUE einfo;
|
||||
{
|
||||
*failed = einfo;
|
||||
return Qnil;
|
||||
|
@ -107,10 +121,17 @@ ip_eval_rescue(VALUE *failed, VALUE einfo)
|
|||
|
||||
static int
|
||||
#if TCL_MAJOR_VERSION >= 8
|
||||
ip_ruby(ClientData clientData, Tcl_Interp *interp,
|
||||
int argc, Tcl_Obj *CONST argv[])
|
||||
ip_ruby(clientData, interp, argc, argv)
|
||||
ClientData clientData;
|
||||
Tcl_Interp *interp;
|
||||
int argc;
|
||||
Tcl_Obj *CONST argv[];
|
||||
#else
|
||||
ip_ruby(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
|
||||
ip_ruby(clientData, interp, argc, argv)
|
||||
ClientData clientData;
|
||||
Tcl_Interp *interp;
|
||||
int argc;
|
||||
char *argv[];
|
||||
#endif
|
||||
{
|
||||
VALUE res;
|
||||
|
@ -143,11 +164,11 @@ ip_ruby(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
|
|||
VALUE eclass = CLASS_OF(failed);
|
||||
Tcl_AppendResult(interp, STR2CSTR(failed), (char*)NULL);
|
||||
if (eclass == eTkCallbackBreak) {
|
||||
return TCL_BREAK;
|
||||
return TCL_BREAK;
|
||||
} else if (eclass == eTkCallbackContinue) {
|
||||
return TCL_CONTINUE;
|
||||
return TCL_CONTINUE;
|
||||
} else {
|
||||
return TCL_ERROR;
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -167,7 +188,8 @@ ip_ruby(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
|
|||
|
||||
/* destroy interpreter */
|
||||
static void
|
||||
ip_free(struct tcltkip *ptr)
|
||||
ip_free(ptr)
|
||||
struct tcltkip *ptr;
|
||||
{
|
||||
DUMP1("Tcl_DeleteInterp");
|
||||
Tcl_DeleteInterp(ptr->ip);
|
||||
|
@ -176,7 +198,8 @@ ip_free(struct tcltkip *ptr)
|
|||
|
||||
/* create and initialize interpreter */
|
||||
static VALUE
|
||||
ip_new(VALUE self)
|
||||
ip_new(self)
|
||||
VALUE self;
|
||||
{
|
||||
struct tcltkip *ptr; /* tcltkip data struct */
|
||||
VALUE obj; /* newly created object */
|
||||
|
@ -192,11 +215,11 @@ ip_new(VALUE self)
|
|||
/* from Tcl_AppInit() */
|
||||
DUMP1("Tcl_Init");
|
||||
if (Tcl_Init(ptr->ip) == TCL_ERROR) {
|
||||
rb_raise(rb_eRuntimeError, "Tcl_Init");
|
||||
rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
|
||||
}
|
||||
DUMP1("Tk_Init");
|
||||
if (Tk_Init(ptr->ip) == TCL_ERROR) {
|
||||
rb_raise(rb_eRuntimeError, "Tk_Init");
|
||||
rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
|
||||
}
|
||||
DUMP1("Tcl_StaticPackage(\"Tk\")");
|
||||
Tcl_StaticPackage(ptr->ip, "Tk", Tk_Init,
|
||||
|
@ -218,7 +241,9 @@ ip_new(VALUE self)
|
|||
|
||||
/* eval string in tcl by Tcl_Eval() */
|
||||
static VALUE
|
||||
ip_eval(VALUE self, VALUE str)
|
||||
ip_eval(self, str)
|
||||
VALUE self;
|
||||
VALUE str;
|
||||
{
|
||||
char *s;
|
||||
char *buf; /* Tcl_Eval requires re-writable string region */
|
||||
|
@ -234,7 +259,7 @@ ip_eval(VALUE self, VALUE str)
|
|||
DUMP2("Tcl_Eval(%s)", buf);
|
||||
ptr->return_value = Tcl_Eval(ptr->ip, buf);
|
||||
if (ptr->return_value == TCL_ERROR) {
|
||||
rb_raise(rb_eRuntimeError, ptr->ip->result);
|
||||
rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
|
||||
}
|
||||
DUMP2("(TCL_Eval result) %d", ptr->return_value);
|
||||
|
||||
|
@ -244,76 +269,77 @@ ip_eval(VALUE self, VALUE str)
|
|||
|
||||
|
||||
static VALUE
|
||||
ip_toUTF8(VALUE self, VALUE str, VALUE encodename)
|
||||
ip_toUTF8(self, str, encodename)
|
||||
VALUE self;
|
||||
VALUE str;
|
||||
VALUE encodename;
|
||||
{
|
||||
#ifndef TCL_UTF_MAX
|
||||
return str;
|
||||
#else
|
||||
Tcl_Interp *interp;
|
||||
Tcl_Encoding encoding;
|
||||
Tcl_DString dstr;
|
||||
struct tcltkip *ptr;
|
||||
char *buff1,*buff2;
|
||||
#ifdef TCL_UTF_MAX
|
||||
Tcl_Interp *interp;
|
||||
Tcl_Encoding encoding;
|
||||
Tcl_DString dstr;
|
||||
struct tcltkip *ptr;
|
||||
char *buf;
|
||||
|
||||
Data_Get_Struct(self,struct tcltkip, ptr);
|
||||
interp = ptr->ip;
|
||||
Data_Get_Struct(self,struct tcltkip, ptr);
|
||||
interp = ptr->ip;
|
||||
|
||||
encoding = Tcl_GetEncoding(interp,STR2CSTR(encodename));
|
||||
buff1 = ALLOCA_N(char,strlen(STR2CSTR(str))+1);
|
||||
strcpy(buff1,STR2CSTR(str));
|
||||
encoding = Tcl_GetEncoding(interp,STR2CSTR(encodename));
|
||||
buf = ALLOCA_N(char,strlen(STR2CSTR(str))+1);
|
||||
strcpy(buf,STR2CSTR(str));
|
||||
|
||||
Tcl_DStringInit(&dstr);
|
||||
Tcl_DStringFree(&dstr);
|
||||
Tcl_ExternalToUtfDString(encoding,buff1,strlen(buff1),&dstr);
|
||||
buff2 = ALLOCA_N(char,Tcl_DStringLength(&dstr)+1);
|
||||
strcpy(buff2,Tcl_DStringValue(&dstr));
|
||||
Tcl_DStringInit(&dstr);
|
||||
Tcl_DStringFree(&dstr);
|
||||
Tcl_ExternalToUtfDString(encoding,buf,strlen(buf),&dstr);
|
||||
str = rb_str_new2(Tcl_DStringValue(&dstr));
|
||||
|
||||
Tcl_FreeEncoding(encoding);
|
||||
Tcl_DStringFree(&dstr);
|
||||
|
||||
return rb_str_new2(buff2);
|
||||
Tcl_FreeEncoding(encoding);
|
||||
Tcl_DStringFree(&dstr);
|
||||
#endif
|
||||
return str;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
ip_fromUTF8(VALUE self, VALUE str, VALUE encodename)
|
||||
ip_fromUTF8(self, str, encodename)
|
||||
VALUE self;
|
||||
VALUE str;
|
||||
VALUE encodename;
|
||||
{
|
||||
#ifndef TCL_UTF_MAX
|
||||
return str;
|
||||
#else
|
||||
Tcl_Interp *interp;
|
||||
Tcl_Encoding encoding;
|
||||
Tcl_DString dstr;
|
||||
struct tcltkip *ptr;
|
||||
char *buff1,*buff2;
|
||||
#ifdef TCL_UTF_MAX
|
||||
Tcl_Interp *interp;
|
||||
Tcl_Encoding encoding;
|
||||
Tcl_DString dstr;
|
||||
struct tcltkip *ptr;
|
||||
char *buf;
|
||||
|
||||
Data_Get_Struct(self,struct tcltkip, ptr);
|
||||
interp = ptr->ip;
|
||||
Data_Get_Struct(self,struct tcltkip, ptr);
|
||||
interp = ptr->ip;
|
||||
|
||||
encoding = Tcl_GetEncoding(interp,STR2CSTR(encodename));
|
||||
buff1 = ALLOCA_N(char,strlen(STR2CSTR(str))+1);
|
||||
strcpy(buff1,STR2CSTR(str));
|
||||
encoding = Tcl_GetEncoding(interp,STR2CSTR(encodename));
|
||||
buf = ALLOCA_N(char,strlen(STR2CSTR(str))+1);
|
||||
strcpy(buf,STR2CSTR(str));
|
||||
|
||||
Tcl_DStringInit(&dstr);
|
||||
Tcl_DStringFree(&dstr);
|
||||
Tcl_UtfToExternalDString(encoding,buff1,strlen(buff1),&dstr);
|
||||
buff2 = ALLOCA_N(char,Tcl_DStringLength(&dstr)+1);
|
||||
strcpy(buff2,Tcl_DStringValue(&dstr));
|
||||
Tcl_DStringInit(&dstr);
|
||||
Tcl_DStringFree(&dstr);
|
||||
Tcl_UtfToExternalDString(encoding,buf,strlen(buf),&dstr);
|
||||
str = rb_str_new2(Tcl_DStringValue(&dstr));
|
||||
|
||||
Tcl_FreeEncoding(encoding);
|
||||
Tcl_DStringFree(&dstr);
|
||||
Tcl_FreeEncoding(encoding);
|
||||
Tcl_DStringFree(&dstr);
|
||||
|
||||
return rb_str_new2(buff2);
|
||||
#endif
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
static VALUE
|
||||
ip_invoke(int argc, VALUE *argv, VALUE obj)
|
||||
ip_invoke_real(argc, argv, obj)
|
||||
int argc;
|
||||
VALUE *argv;
|
||||
VALUE obj;
|
||||
{
|
||||
struct tcltkip *ptr; /* tcltkip data struct */
|
||||
int i;
|
||||
int object = 0;
|
||||
Tcl_CmdInfo info;
|
||||
char *cmd;
|
||||
char **av = (char **)NULL;
|
||||
|
@ -332,63 +358,115 @@ ip_invoke(int argc, VALUE *argv, VALUE obj)
|
|||
if (!Tcl_GetCommandInfo(ptr->ip, cmd, &info)) {
|
||||
rb_raise(rb_eNameError, "invalid command name `%s'", cmd);
|
||||
}
|
||||
#if TCL_MAJOR_VERSION >= 8
|
||||
object = info.isNativeObjectProc;
|
||||
#endif
|
||||
|
||||
/* memory allocation for arguments of this command */
|
||||
if (object) {
|
||||
#if TCL_MAJOR_VERSION >= 8
|
||||
/* object interface */
|
||||
ov = (Tcl_Obj **)ALLOCA_N(Tcl_Obj *, argc+1);
|
||||
for (i = 0; i < argc; ++i) {
|
||||
char *s = STR2CSTR(argv[i]);
|
||||
ov[i] = Tcl_NewStringObj(s, strlen(s));
|
||||
}
|
||||
ov[argc] = (Tcl_Obj *)NULL;
|
||||
if (info.isNativeObjectProc) {
|
||||
/* object interface */
|
||||
ov = (Tcl_Obj **)ALLOCA_N(Tcl_Obj *, argc+1);
|
||||
for (i = 0; i < argc; ++i) {
|
||||
char *s = STR2CSTR(argv[i]);
|
||||
ov[i] = Tcl_NewStringObj(s, strlen(s));
|
||||
Tcl_IncrRefCount(ov[i]);
|
||||
}
|
||||
ov[argc] = (Tcl_Obj *)NULL;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
} else {
|
||||
{
|
||||
/* string interface */
|
||||
av = (char **)ALLOCA_N(char *, argc+1);
|
||||
for (i = 0; i < argc; ++i) {
|
||||
char *s = STR2CSTR(argv[i]);
|
||||
av = (char **)ALLOCA_N(char *, argc+1);
|
||||
for (i = 0; i < argc; ++i) {
|
||||
char *s = STR2CSTR(argv[i]);
|
||||
|
||||
av[i] = ALLOCA_N(char, strlen(s)+1);
|
||||
strcpy(av[i], s);
|
||||
}
|
||||
av[argc] = (char *)NULL;
|
||||
av[i] = ALLOCA_N(char, strlen(s)+1);
|
||||
strcpy(av[i], s);
|
||||
}
|
||||
av[argc] = (char *)NULL;
|
||||
}
|
||||
|
||||
Tcl_ResetResult(ptr->ip);
|
||||
|
||||
/* Invoke the C procedure */
|
||||
if (object) {
|
||||
#if TCL_MAJOR_VERSION >= 8
|
||||
int dummy;
|
||||
ptr->return_value = (*info.objProc)(info.objClientData,
|
||||
ptr->ip, argc, ov);
|
||||
if (info.isNativeObjectProc) {
|
||||
int dummy;
|
||||
ptr->return_value = (*info.objProc)(info.objClientData,
|
||||
ptr->ip, argc, ov);
|
||||
|
||||
/* get the string value from the result object */
|
||||
resultPtr = Tcl_GetObjResult(ptr->ip);
|
||||
Tcl_SetResult(ptr->ip, Tcl_GetStringFromObj(resultPtr, &dummy),
|
||||
TCL_VOLATILE);
|
||||
/* get the string value from the result object */
|
||||
resultPtr = Tcl_GetObjResult(ptr->ip);
|
||||
Tcl_SetResult(ptr->ip, Tcl_GetStringFromObj(resultPtr, &dummy),
|
||||
TCL_VOLATILE);
|
||||
|
||||
for (i=0; i<argc; i++) {
|
||||
Tcl_DecrRefCount(ov[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
} else {
|
||||
ptr->return_value = (*info.proc)(info.clientData,
|
||||
ptr->ip, argc, av);
|
||||
{
|
||||
ptr->return_value = (*info.proc)(info.clientData,
|
||||
ptr->ip, argc, av);
|
||||
}
|
||||
|
||||
if (ptr->return_value == TCL_ERROR) {
|
||||
rb_raise(rb_eRuntimeError, ptr->ip->result);
|
||||
rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
|
||||
}
|
||||
|
||||
/* pass back the result (as string) */
|
||||
return(rb_str_new2(ptr->ip->result));
|
||||
return rb_str_new2(ptr->ip->result);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
ip_invoke(argc, argv, obj)
|
||||
int argc;
|
||||
VALUE *argv;
|
||||
VALUE obj;
|
||||
{
|
||||
struct invoke_queue *tmp, *p;
|
||||
VALUE result = rb_thread_current();
|
||||
|
||||
if (result == main_thread) {
|
||||
return ip_invoke_real(argc, argv, obj);
|
||||
}
|
||||
tmp = ALLOC(struct invoke_queue);
|
||||
tmp->obj = obj;
|
||||
tmp->argc = argc;
|
||||
tmp->argv = ALLOC_N(VALUE, argc);
|
||||
MEMCPY(tmp->argv, argv, VALUE, argc);
|
||||
tmp->thread = result;
|
||||
tmp->done = 0;
|
||||
|
||||
tmp->next = iqueue;
|
||||
iqueue = tmp;
|
||||
|
||||
rb_thread_stop();
|
||||
result = tmp->result;
|
||||
if (iqueue == tmp) {
|
||||
iqueue = tmp->next;
|
||||
free(tmp->argv);
|
||||
free(tmp);
|
||||
return result;
|
||||
}
|
||||
|
||||
p = iqueue;
|
||||
while (p->next) {
|
||||
if (p->next == tmp) {
|
||||
p->next = tmp->next;
|
||||
free(tmp->argv);
|
||||
free(tmp);
|
||||
break;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* get return code from Tcl_Eval() */
|
||||
static VALUE
|
||||
ip_retval(VALUE self)
|
||||
ip_retval(self)
|
||||
VALUE self;
|
||||
{
|
||||
struct tcltkip *ptr; /* tcltkip data struct */
|
||||
|
||||
|
@ -402,13 +480,14 @@ ip_retval(VALUE self)
|
|||
static void
|
||||
_macinit()
|
||||
{
|
||||
tcl_macQdPtr = &qd; /* setup QuickDraw globals */
|
||||
Tcl_MacSetEventProc(TkMacConvertEvent); /* setup event handler */
|
||||
tcl_macQdPtr = &qd; /* setup QuickDraw globals */
|
||||
Tcl_MacSetEventProc(TkMacConvertEvent); /* setup event handler */
|
||||
}
|
||||
#endif
|
||||
|
||||
/*---- initialization ----*/
|
||||
void Init_tcltklib()
|
||||
void
|
||||
Init_tcltklib()
|
||||
{
|
||||
extern VALUE rb_argv0; /* the argv[0] */
|
||||
|
||||
|
@ -428,6 +507,7 @@ void Init_tcltklib()
|
|||
rb_define_method(ip, "_return_value", ip_retval, 0);
|
||||
rb_define_method(ip, "mainloop", lib_mainloop, 0);
|
||||
|
||||
main_thread = rb_thread_current();
|
||||
#ifdef __MACOS__
|
||||
_macinit();
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
MANIFEST
|
||||
extconf.rb
|
||||
depend
|
||||
tkutil.c
|
||||
lib/tk.rb
|
||||
lib/tkafter.rb
|
||||
lib/tkbgerror.rb
|
||||
lib/tkcanvas.rb
|
||||
lib/tkclass.rb
|
||||
lib/tkdialog.rb
|
||||
lib/tkentry.rb
|
||||
lib/tkfont.rb
|
||||
lib/tkmenubar.rb
|
||||
lib/tkmngfocus.rb
|
||||
lib/tkpalette.rb
|
||||
lib/tkscrollbox.rb
|
||||
lib/tktext.rb
|
||||
lib/tkvirtevent.rb
|
||||
sample/tkbiff.rb
|
||||
sample/tkbrowse.rb
|
||||
sample/tkdialog.rb
|
||||
sample/tkfrom.rb
|
||||
sample/tkhello.rb
|
||||
sample/tkline.rb
|
||||
sample/tktimer.rb
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче