git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@518 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
matz 1999-08-13 05:37:52 +00:00
Родитель 210367ec88
Коммит 0a64817fb8
124 изменённых файлов: 14604 добавлений и 10219 удалений

Просмотреть файл

@ -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

16
ext/Setup.emx Normal file
Просмотреть файл

@ -0,0 +1,16 @@
option nodynamic
#Win32API
curses
#dbm
etc
fcntl
#gdbm
md5
nkf
#pty
#readline
#sdbm
socket
#tcltklib
#tk

Просмотреть файл

@ -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

7
ext/Win32API/MANIFEST Normal file
Просмотреть файл

@ -0,0 +1,7 @@
MANIFEST
depend
MANIFEST
Win32API.c
extconf.rb
getch.rb
point.rb

231
ext/Win32API/Win32API.c Normal file
Просмотреть файл

@ -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

7
ext/Win32API/extconf.rb Normal file
Просмотреть файл

@ -0,0 +1,7 @@
case PLATFORM
when /cygwin/,/mingw/
$CFLAGS = "-fno-defer-pop"
create_makefile("Win32API")
when /win32/
create_makefile("Win32API")
end

5
ext/Win32API/getch.rb Normal file
Просмотреть файл

@ -0,0 +1,5 @@
require 'Win32API'
getch = Win32API.new("crtdll", "_getch", [], 'L')
puts getch.Call.chr

18
ext/Win32API/point.rb Normal file
Просмотреть файл

@ -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"

33
ext/aix_mksym.rb Normal file
Просмотреть файл

@ -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;

72
ext/etc/etc.txt Normal file
Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

1
ext/gdbm/README Normal file
Просмотреть файл

@ -0,0 +1 @@
gdbm ext-library for Ruby 1.3 or later

1
ext/gdbm/depend Normal file
Просмотреть файл

@ -0,0 +1 @@
gdbm.o: gdbm.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h

7
ext/gdbm/extconf.rb Normal file
Просмотреть файл

@ -0,0 +1,7 @@
require 'mkmf'
dir_config("gdbm")
if have_library("gdbm", "gdbm_open") and
have_header("gdbm.h")
create_makefile("gdbm")
end

604
ext/gdbm/gdbm.c Normal file
Просмотреть файл

@ -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

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -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

38
ext/md5/md5.txt Normal file
Просмотреть файл

@ -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);
}

7
ext/nkf/MANIFEST Normal file
Просмотреть файл

@ -0,0 +1,7 @@
MANIFEST
depend
extconf.rb
lib/kconv.rb
nkf.c
nkf1.7/nkf.c
test.rb

1
ext/nkf/depend Normal file
Просмотреть файл

@ -0,0 +1 @@
nkf.o : nkf.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h nkf1.7/nkf.c

2
ext/nkf/extconf.rb Normal file
Просмотреть файл

@ -0,0 +1,2 @@
require 'mkmf'
create_makefile('nkf')

58
ext/nkf/lib/kconv.rb Normal file
Просмотреть файл

@ -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

206
ext/nkf/nkf.c Normal file
Просмотреть файл

@ -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));
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

318
ext/nkf/test.rb Normal file
Просмотреть файл

@ -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&#0X-%@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'])

11
ext/pty/MANIFEST Normal file
Просмотреть файл

@ -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

93
ext/pty/README Normal file
Просмотреть файл

@ -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.

22
ext/pty/README.expect Normal file
Просмотреть файл

@ -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.

21
ext/pty/README.expect.jp Normal file
Просмотреть файл

@ -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を返します
このメソッドがブロック付きで呼ばれた場合には,マッチした要素の
配列がブロック引数として渡され,ブロックが評価されます.

89
ext/pty/README.jp Normal file
Просмотреть файл

@ -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
まで電子メールでバグレポートをお送りください.

56
ext/pty/expect_sample.rb Normal file
Просмотреть файл

@ -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"

10
ext/pty/extconf.rb Normal file
Просмотреть файл

@ -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

36
ext/pty/lib/expect.rb Normal file
Просмотреть файл

@ -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

497
ext/pty/pty.c Normal file
Просмотреть файл

@ -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);
}

38
ext/pty/script.rb Normal file
Просмотреть файл

@ -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"

96
ext/pty/shl.rb Normal file
Просмотреть файл

@ -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;

5
ext/sdbm/MANIFEST Normal file
Просмотреть файл

@ -0,0 +1,5 @@
MANIFEST
_sdbm.c
extconf.rb
init.c
sdbm.h

977
ext/sdbm/_sdbm.c Normal file
Просмотреть файл

@ -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;
}

3
ext/sdbm/extconf.rb Normal file
Просмотреть файл

@ -0,0 +1,3 @@
require 'mkmf'
create_makefile("sdbm")

584
ext/sdbm/init.c Normal file
Просмотреть файл

@ -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);
}

84
ext/sdbm/sdbm.h Normal file
Просмотреть файл

@ -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

172
ext/socket/addrinfo.h Normal file
Просмотреть файл

@ -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

676
ext/socket/getaddrinfo.c Normal file
Просмотреть файл

@ -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;
}

250
ext/socket/getnameinfo.c Normal file
Просмотреть файл

@ -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;
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

43
ext/socket/sockport.h Normal file
Просмотреть файл

@ -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

25
ext/tk/MANIFEST Normal file
Просмотреть файл

@ -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

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше