[前][次][番号順一覧][スレッド一覧]

ruby-changes:33903

From: akr <ko1@a...>
Date: Sun, 18 May 2014 10:48:55 +0900 (JST)
Subject: [ruby-changes:33903] akr:r45984 (trunk): * ext/etc/etc.c: Etc.sysconf, Etc.confstr and IO#pathconf implemented.

akr	2014-05-18 10:48:47 +0900 (Sun, 18 May 2014)

  New Revision: 45984

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=45984

  Log:
    * ext/etc/etc.c: Etc.sysconf, Etc.confstr and IO#pathconf implemented.
    
    * ext/etc/extconf.rb: Check sysconf(), confstr() and fpathconf().
    
    * ext/etc/mkconstants.rb: New file.
    
     [ruby-core:62600] [Feature #9842]

  Added files:
    trunk/ext/etc/mkconstants.rb
  Modified files:
    trunk/.gitignore
    trunk/ChangeLog
    trunk/NEWS
    trunk/ext/etc/depend
    trunk/ext/etc/etc.c
    trunk/ext/etc/extconf.rb
    trunk/test/etc/test_etc.rb
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 45983)
+++ ChangeLog	(revision 45984)
@@ -1,3 +1,13 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Sun May 18 10:46:04 2014  Tanaka Akira  <akr@f...>
+
+	* ext/etc/etc.c: Etc.sysconf, Etc.confstr and IO#pathconf implemented.
+
+	* ext/etc/extconf.rb: Check sysconf(), confstr() and fpathconf().
+
+	* ext/etc/mkconstants.rb: New file.
+
+	   [ruby-core:62600] [Feature #9842]
+
 Sun May 18 09:58:17 2014  Tanaka Akira  <akr@f...>
 
 	* ext/etc/etc.c: Etc.uname method implemented.
Index: ext/etc/depend
===================================================================
--- ext/etc/depend	(revision 45983)
+++ ext/etc/depend	(revision 45984)
@@ -1,3 +1,8 @@ https://github.com/ruby/ruby/blob/trunk/ext/etc/depend#L1
-etc.o : etc.c $(HDRS) $(ruby_headers) \
+etc.o : etc.c constdefs.h $(HDRS) $(ruby_headers) \
   $(hdrdir)/ruby/encoding.h \
   $(hdrdir)/ruby/oniguruma.h
+
+constdefs.h : $(srcdir)/mkconstants.rb
+	@echo "generating constant definitions"
+	@$(RUBY) $(srcdir)/mkconstants.rb -o constdefs.h
+
Index: ext/etc/mkconstants.rb
===================================================================
--- ext/etc/mkconstants.rb	(revision 0)
+++ ext/etc/mkconstants.rb	(revision 45984)
@@ -0,0 +1,329 @@ https://github.com/ruby/ruby/blob/trunk/ext/etc/mkconstants.rb#L1
+require 'optparse'
+require 'erb'
+
+C_ESC = {
+  "\\" => "\\\\",
+  '"' => '\"',
+  "\n" => '\n',
+}
+
+0x00.upto(0x1f) {|ch| C_ESC[[ch].pack("C")] ||= "\\%03o" % ch }
+0x7f.upto(0xff) {|ch| C_ESC[[ch].pack("C")] = "\\%03o" % ch }
+C_ESC_PAT = Regexp.union(*C_ESC.keys)
+
+def c_str(str)
+  '"' + str.gsub(C_ESC_PAT) {|s| C_ESC[s]} + '"'
+end
+
+opt = OptionParser.new
+
+opt.def_option('-h', 'help') {
+  puts opt
+  exit 0
+}
+
+opt_o = nil
+opt.def_option('-o FILE', 'specify output file') {|filename|
+  opt_o = filename
+}
+
+opt_H = nil
+opt.def_option('-H FILE', 'specify output header file') {|filename|
+  opt_H = filename
+}
+
+opt.parse!
+
+h = {}
+COMMENTS = Hash.new { |h, name| h[name] = name }
+
+DATA.each_line {|s|
+  next if /\A\s*(\#|\z)/ =~ s
+  name, default_value, comment = s.chomp.split(/\s+/, 3)
+
+  default_value = nil if default_value == 'nil'
+
+  if h.has_key? name
+    warn "#{$.}: warning: duplicate name: #{name}"
+    next
+  end
+  h[name] = default_value
+  COMMENTS[name] = comment
+}
+DEFS = h.to_a
+
+def each_const
+  DEFS.each {|name, default_value|
+    yield name, default_value
+  }
+end
+
+def each_name(pat)
+  DEFS.each {|name, default_value|
+    next if pat !~ name
+    yield name
+  }
+end
+
+ERB.new(<<'EOS', nil, '%').def_method(Object, "gen_const_decls")
+% each_const {|name, default_value|
+#if !defined(<%=name%>)
+# if defined(HAVE_CONST_<%=name.upcase%>)
+#  define <%=name%> <%=name%>
+%if default_value
+# else
+#  define <%=name%> <%=default_value%>
+%end
+# endif
+#endif
+% }
+EOS
+
+ERB.new(<<'EOS', nil, '%').def_method(Object, "gen_const_defs")
+% each_const {|name, default_value|
+#if defined(<%=name%>)
+    /* <%= COMMENTS[name] %> */
+    rb_define_const(mod, <%=c_str name.sub(/\A_*/, '')%>, INTEGER2NUM(<%=name%>));
+#endif
+% }
+EOS
+
+header_result = ERB.new(<<'EOS', nil, '%').result(binding)
+/* autogenerated file */
+
+<%= gen_const_decls %>
+EOS
+
+result = ERB.new(<<'EOS', nil, '%').result(binding)
+/* autogenerated file */
+
+#ifdef HAVE_LONG_LONG
+#define INTEGER2NUM(n) \
+    (FIXNUM_MAX < (n) ? ULL2NUM(n) : \
+     FIXNUM_MIN > (LONG_LONG)(n) ? LL2NUM(n) : \
+     LONG2FIX(n))
+#else
+#define INTEGER2NUM(n) \
+    (FIXNUM_MAX < (n) ? ULONG2NUM(n) : \
+     FIXNUM_MIN > (long)(n) ? LONG2NUM(n) : \
+     LONG2FIX(n))
+#endif
+
+static void
+init_constants(VALUE mod)
+{
+<%= gen_const_defs %>
+}
+EOS
+
+if opt_H
+  File.open(opt_H, 'w') {|f|
+    f << header_result
+  }
+else
+  result = header_result + result
+end
+
+if opt_o
+  File.open(opt_o, 'w') {|f|
+    f << result
+  }
+else
+  $stdout << result
+end
+
+__END__
+# SUSv4
+_SC_AIO_LISTIO_MAX
+_SC_AIO_MAX
+_SC_AIO_PRIO_DELTA_MAX
+_SC_ARG_MAX
+_SC_ATEXIT_MAX
+_SC_BC_BASE_MAX
+_SC_BC_DIM_MAX
+_SC_BC_SCALE_MAX
+_SC_BC_STRING_MAX
+_SC_CHILD_MAX
+_SC_CLK_TCK
+_SC_COLL_WEIGHTS_MAX
+_SC_DELAYTIMER_MAX
+_SC_EXPR_NEST_MAX
+_SC_HOST_NAME_MAX
+_SC_IOV_MAX
+_SC_LINE_MAX
+_SC_LOGIN_NAME_MAX
+_SC_NGROUPS_MAX
+_SC_GETGR_R_SIZE_MAX
+_SC_GETPW_R_SIZE_MAX
+_SC_MQ_OPEN_MAX
+_SC_MQ_PRIO_MAX
+_SC_OPEN_MAX
+_SC_ADVISORY_INFO
+_SC_BARRIERS
+_SC_ASYNCHRONOUS_IO
+_SC_CLOCK_SELECTION
+_SC_CPUTIME
+_SC_FSYNC
+_SC_IPV6
+_SC_JOB_CONTROL
+_SC_MAPPED_FILES
+_SC_MEMLOCK
+_SC_MEMLOCK_RANGE
+_SC_MEMORY_PROTECTION
+_SC_MESSAGE_PASSING
+_SC_MONOTONIC_CLOCK
+_SC_PRIORITIZED_IO
+_SC_PRIORITY_SCHEDULING
+_SC_RAW_SOCKETS
+_SC_READER_WRITER_LOCKS
+_SC_REALTIME_SIGNALS
+_SC_REGEXP
+_SC_SAVED_IDS
+_SC_SEMAPHORES
+_SC_SHARED_MEMORY_OBJECTS
+_SC_SHELL
+_SC_SPAWN
+_SC_SPIN_LOCKS
+_SC_SPORADIC_SERVER
+_SC_SS_REPL_MAX
+_SC_SYNCHRONIZED_IO
+_SC_THREAD_ATTR_STACKADDR
+_SC_THREAD_ATTR_STACKSIZE
+_SC_THREAD_CPUTIME
+_SC_THREAD_PRIO_INHERIT
+_SC_THREAD_PRIO_PROTECT
+_SC_THREAD_PRIORITY_SCHEDULING
+_SC_THREAD_PROCESS_SHARED
+_SC_THREAD_ROBUST_PRIO_INHERIT
+_SC_THREAD_ROBUST_PRIO_PROTECT
+_SC_THREAD_SAFE_FUNCTIONS
+_SC_THREAD_SPORADIC_SERVER
+_SC_THREADS
+_SC_TIMEOUTS
+_SC_TIMERS
+_SC_TRACE
+_SC_TRACE_EVENT_FILTER
+_SC_TRACE_EVENT_NAME_MAX
+_SC_TRACE_INHERIT
+_SC_TRACE_LOG
+_SC_TRACE_NAME_MAX
+_SC_TRACE_SYS_MAX
+_SC_TRACE_USER_EVENT_MAX
+_SC_TYPED_MEMORY_OBJECTS
+_SC_VERSION
+_SC_V7_ILP32_OFF32
+_SC_V7_ILP32_OFFBIG
+_SC_V7_LP64_OFF64
+_SC_V7_LPBIG_OFFBIG
+_SC_V6_ILP32_OFF32
+_SC_V6_ILP32_OFFBIG
+_SC_V6_LP64_OFF64
+_SC_V6_LPBIG_OFFBIG
+_SC_2_C_BIND
+_SC_2_C_DEV
+_SC_2_CHAR_TERM
+_SC_2_FORT_DEV
+_SC_2_FORT_RUN
+_SC_2_LOCALEDEF
+_SC_2_PBS
+_SC_2_PBS_ACCOUNTING
+_SC_2_PBS_CHECKPOINT
+_SC_2_PBS_LOCATE
+_SC_2_PBS_MESSAGE
+_SC_2_PBS_TRACK
+_SC_2_SW_DEV
+_SC_2_UPE
+_SC_2_VERSION
+_SC_PAGE_SIZE
+_SC_PAGESIZE
+_SC_THREAD_DESTRUCTOR_ITERATIONS
+_SC_THREAD_KEYS_MAX
+_SC_THREAD_STACK_MIN
+_SC_THREAD_THREADS_MAX
+_SC_RE_DUP_MAX
+_SC_RTSIG_MAX
+_SC_SEM_NSEMS_MAX
+_SC_SEM_VALUE_MAX
+_SC_SIGQUEUE_MAX
+_SC_STREAM_MAX
+_SC_SYMLOOP_MAX
+_SC_TIMER_MAX
+_SC_TTY_NAME_MAX
+_SC_TZNAME_MAX
+_SC_XOPEN_CRYPT
+_SC_XOPEN_ENH_I18N
+_SC_XOPEN_REALTIME
+_SC_XOPEN_REALTIME_THREADS
+_SC_XOPEN_SHM
+_SC_XOPEN_STREAMS
+_SC_XOPEN_UNIX
+_SC_XOPEN_UUCP
+_SC_XOPEN_VERSION
+
+# non-standard
+_SC_PHYS_PAGES
+_SC_AVPHYS_PAGES
+_SC_NPROCESSORS_CONF
+_SC_NPROCESSORS_ONLN
+_SC_CPUSET_SIZE
+
+# SUSv4
+_CS_PATH
+_CS_POSIX_V7_ILP32_OFF32_CFLAGS
+_CS_POSIX_V7_ILP32_OFF32_LDFLAGS
+_CS_POSIX_V7_ILP32_OFF32_LIBS
+_CS_POSIX_V7_ILP32_OFFBIG_CFLAGS
+_CS_POSIX_V7_ILP32_OFFBIG_LDFLAGS
+_CS_POSIX_V7_ILP32_OFFBIG_LIBS
+_CS_POSIX_V7_LP64_OFF64_CFLAGS
+_CS_POSIX_V7_LP64_OFF64_LDFLAGS
+_CS_POSIX_V7_LP64_OFF64_LIBS
+_CS_POSIX_V7_LPBIG_OFFBIG_CFLAGS
+_CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGS
+_CS_POSIX_V7_LPBIG_OFFBIG_LIBS
+_CS_POSIX_V7_THREADS_CFLAGS
+_CS_POSIX_V7_THREADS_LDFLAGS
+_CS_POSIX_V7_WIDTH_RESTRICTED_ENVS
+_CS_V7_ENV
+_CS_POSIX_V6_ILP32_OFF32_CFLAGS
+_CS_POSIX_V6_ILP32_OFF32_LDFLAGS
+_CS_POSIX_V6_ILP32_OFF32_LIBS
+_CS_POSIX_V6_ILP32_OFFBIG_CFLAGS
+_CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS
+_CS_POSIX_V6_ILP32_OFFBIG_LIBS
+_CS_POSIX_V6_LP64_OFF64_CFLAGS
+_CS_POSIX_V6_LP64_OFF64_LDFLAGS
+_CS_POSIX_V6_LP64_OFF64_LIBS
+_CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS
+_CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS
+_CS_POSIX_V6_LPBIG_OFFBIG_LIBS
+_CS_POSIX_V6_WIDTH_RESTRICTED_ENVS
+_CS_V6_ENV
+
+# non-standard
+_CS_GNU_LIBC_VERSION
+_CS_GNU_LIBPTHREAD_VERSION
+
+# SUSv4
+_PC_FILESIZEBITS
+_PC_LINK_MAX
+_PC_MAX_CANON
+_PC_MAX_INPUT
+_PC_NAME_MAX
+_PC_PATH_MAX
+_PC_PIPE_BUF
+_PC_2_SYMLINKS
+_PC_ALLOC_SIZE_MIN
+_PC_REC_INCR_XFER_SIZE
+_PC_REC_MAX_XFER_SIZE
+_PC_REC_MIN_XFER_SIZE
+_PC_REC_XFER_ALIGN
+_PC_SYMLINK_MAX
+_PC_CHOWN_RESTRICTED
+_PC_NO_TRUNC
+_PC_VDISABLE
+_PC_ASYNC_IO
+_PC_PRIO_IO
+_PC_SYNC_IO
+_PC_TIMESTAMP_RESOLUTION
+

Property changes on: ext/etc/mkconstants.rb
___________________________________________________________________
Added: svn:eol-style
   + LF

Index: ext/etc/extconf.rb
===================================================================
--- ext/etc/extconf.rb	(revision 45983)
+++ ext/etc/extconf.rb	(revision 45984)
@@ -14,6 +14,10 @@ have_func("getgrent") https://github.com/ruby/ruby/blob/trunk/ext/etc/extconf.rb#L14
 sysconfdir = RbConfig.expand(RbConfig::CONFIG["sysconfdir"].dup, "prefix"=>"", "DESTDIR"=>"")
 $defs.push("-DSYSCONFDIR=#{Shellwords.escape(sysconfdir.dump)}")
 
+have_func("sysconf")
+have_func("confstr")
+have_func("fpathconf")
+
 have_struct_member('struct passwd', 'pw_gecos', 'pwd.h')
 have_struct_member('struct passwd', 'pw_change', 'pwd.h')
 have_struct_member('struct passwd', 'pw_quota', 'pwd.h')
Index: ext/etc/etc.c
===================================================================
--- ext/etc/etc.c	(revision 45983)
+++ ext/etc/etc.c	(revision 45984)
@@ -9,6 +9,7 @@ https://github.com/ruby/ruby/blob/trunk/ext/etc/etc.c#L9
 
 #include "ruby.h"
 #include "ruby/encoding.h"
+#include "ruby/io.h"
 
 #include <sys/types.h>
 #ifdef HAVE_UNISTD_H
@@ -23,6 +24,8 @@ https://github.com/ruby/ruby/blob/trunk/ext/etc/etc.c#L24
 #include <grp.h>
 #endif
 
+#include <errno.h>
+
 #ifdef HAVE_SYS_UTSNAME_H
 #include <sys/utsname.h>
 #endif
@@ -44,6 +47,8 @@ char *getenv(); https://github.com/ruby/ruby/blob/trunk/ext/etc/etc.c#L47
 #endif
 char *getlogin();
 
+#include "constdefs.h"
+
 /* call-seq:
  *	getlogin	->  String
  *
@@ -684,6 +689,126 @@ etc_uname(VALUE obj) https://github.com/ruby/ruby/blob/trunk/ext/etc/etc.c#L689
 #define etc_uname rb_f_notimplement
 #endif
 
+#ifdef HAVE_SYSCONF
+/*
+ * Returns system configuration variable using sysconf().
+ *
+ * _name_ should be a constant undef <code>Etc</code> which begins with <code>SC_</code>.
+ *
+ * The return value is an integer or nil.
+ * nil means indefinite limit.  (sysconf() returns -1 but errno is not set.)
+ *
+ *   Etc.sysconf(Etc::SC_ARG_MAX) #=> 2097152
+ *
+ *   # Number of processors.
+ *   # It is not standardized.
+ *   Etc.sysconf(Etc::SC_NPROCESSORS_ONLN) #=> 4
+ *
+ */
+static VALUE
+etc_sysconf(VALUE obj, VALUE arg)
+{
+    int name;
+    long ret;
+
+    name = NUM2INT(arg);
+
+    errno = 0;
+    ret = sysconf(name);
+    if (ret == -1) {
+        if (errno == 0) /* no limit */
+            return Qnil;
+        rb_sys_fail("sysconf");
+    }
+    return LONG2NUM(ret);
+}
+#else
+#define etc_sysconf rb_f_notimplement
+#endif
+
+#ifdef HAVE_CONFSTR
+/*
+ * Returns system configuration variable using confstr().
+ *
+ * _name_ should be a constant undef <code>Etc</code> which begins with <code>CS_</code>.
+ *
+ * The return value is a string or nil.
+ * nil means no configuration-defined value.  (confstr() returns 0 but errno is not set.)
+ *
+ *   Etc.confstr(Etc::CS_PATH) #=> "/bin:/usr/bin"
+ *
+ *   # GNU/Linux
+ *   Etc.confstr(Etc::CS_GNU_LIBC_VERSION) #=> "glibc 2.18"
+ *   Etc.confstr(Etc::CS_GNU_LIBPTHREAD_VERSION) #=> "NPTL 2.18"
+ *
+ */
+static VALUE
+etc_confstr(VALUE obj, VALUE arg)
+{
+    int name;
+    char localbuf[128], *buf = localbuf;
+    size_t bufsize = sizeof(localbuf), ret;
+    VALUE tmp;
+
+    name = NUM2INT(arg);
+
+    errno = 0;
+    ret = confstr(name, buf, bufsize);
+    if (bufsize < ret) {
+        bufsize = ret;
+        buf = ALLOCV_N(char, tmp, bufsize);
+        errno = 0;
+        ret = confstr(name, buf, bufsize);
+    }
+    if (bufsize < ret)
+        rb_bug("required buffer size for confstr() changed dynamically.");
+    if (ret == 0) {
+        if (errno == 0) /* no configuration-defined value */
+            return Qnil;
+        rb_sys_fail("confstr");
+    }
+    return rb_str_new_cstr(buf);
+}
+#else
+#define etc_confstr rb_f_notimplement
+#endif
+
+#ifdef HAVE_FPATHCONF
+/*
+ * Returns pathname configuration variable using fpathconf().
+ *
+ * _name_ should be a constant undef <code>Etc</code> which begins with <code>PC_</code>.
+ *
+ * The return value is an integer or nil.
+ * nil means indefinite limit.  (fpathconf() returns -1 but errno is not set.)
+ *
+ *   open("/") {|f| p f.pathconf(Etc::PC_NAME_MAX) } #=> 255
+ *
+ */
+static VALUE
+io_pathconf(VALUE io, VALUE arg)
+{
+    int name;
+    long ret;
+    rb_io_t *fptr;
+
+    name = NUM2INT(arg);
+
+    GetOpenFile(io, fptr);
+
+    errno = 0;
+    ret = fpathconf(fptr->fd, name);
+    if (ret == -1) {
+        if (errno == 0) /* no limit */
+            return Qnil;
+        rb_sys_fail("fpathconf");
+    }
+    return LONG2NUM(ret);
+}
+#else
+#define io_pathconf rb_f_notimplement
+#endif
+
 /*
  * The Etc module provides access to information typically stored in
  * files in the /etc directory on Unix systems.
@@ -716,6 +841,8 @@ Init_etc(void) https://github.com/ruby/ruby/blob/trunk/ext/etc/etc.c#L841
     VALUE mEtc;
 
     mEtc = rb_define_module("Etc");
+    init_constants(mEtc);
+
     rb_define_module_function(mEtc, "getlogin", etc_getlogin, 0);
 
     rb_define_module_function(mEtc, "getpwuid", etc_getpwuid, -1);
@@ -734,6 +861,9 @@ Init_etc(void) https://github.com/ruby/ruby/blob/trunk/ext/etc/etc.c#L861
     rb_define_module_function(mEtc, "sysconfdir", etc_sysconfdir, 0);
     rb_define_module_function(mEtc, "systmpdir", etc_systmpdir, 0);
     rb_define_module_function(mEtc, "uname", etc_uname, 0);
+    rb_define_module_function(mEtc, "sysconf", etc_sysconf, 1);
+    rb_define_module_function(mEtc, "confstr", etc_confstr, 1);
+    rb_define_method(rb_cIO, "pathconf", io_pathconf, 1);
 
     sPasswd =  rb_struct_define_under(mEtc, "Passwd",
 				      "name",
Index: NEWS
===================================================================
--- NEWS	(revision 45983)
+++ NEWS	(revision 45984)
@@ -86,6 +86,9 @@ with all sufficient information, see the https://github.com/ruby/ruby/blob/trunk/NEWS#L86
 * Etc
   * New methods:
     * Etc.uname
+    * Etc.sysconf
+    * Etc.confstr
+    * IO#pathconf
 
 * Find, Pathname
   * Extended methods:
Index: test/etc/test_etc.rb
===================================================================
--- test/etc/test_etc.rb	(revision 45983)
+++ test/etc/test_etc.rb	(revision 45984)
@@ -125,4 +125,38 @@ class TestEtc < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/etc/test_etc.rb#L125
       assert_kind_of(String, uname[sym])
     }
   end
+
+  def test_sysconf
+    begin
+      Etc.sysconf
+    rescue NotImplementedError
+      return
+    rescue ArgumentError
+    end
+    assert_kind_of(Integer, Etc.sysconf(Etc::SC_CLK_TCK))
+  end
+
+  def test_confstr
+    begin
+      Etc.confstr
+    rescue NotImplementedError
+      return
+    rescue ArgumentError
+    end
+    assert_kind_of(String, Etc.confstr(Etc::CS_PATH))
+  end
+
+  def test_pathconf
+    begin
+      Etc.confstr
+    rescue NotImplementedError
+      return
+    rescue ArgumentError
+    end
+    IO.pipe {|r, w|
+      val = r.pathconf(Etc::PC_PIPE_BUF)
+      assert(val.nil? || val.kind_of?(Integer))
+    }
+  end
+
 end
Index: .gitignore
===================================================================
--- .gitignore	(revision 45983)
+++ .gitignore	(revision 45984)
@@ -110,6 +110,9 @@ y.tab.c https://github.com/ruby/ruby/blob/trunk/.gitignore#L110
 /ext/dl/callback/callback-*.c
 /ext/dl/callback/callback.c
 
+# /ext/etc/
+/ext/etc/constdefs.h
+
 # /ext/rbconfig/
 /ext/rbconfig/sizeof/sizes.c
 

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]