mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	* parse.y (dsym): :"symbol string" style should not contain `\0'.
* process.c (proc_detach): new method Proc#detach(pid) which create background watcher thread to issue waitpid. [new] * process.c (rb_detach_process): utility function to detach process from C code. * ext/pty/pty.c (pty_finalize_syswait): terminate watcher thread, and detach child process (by creating new idle waitpid watcher thread). * ext/pty/pty.c (pty_syswait): may lost signal stopped child. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3561 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
		
							parent
							
								
									5208fec1cf
								
							
						
					
					
						commit
						9d77639f30
					
				
					 9 changed files with 119 additions and 100 deletions
				
			
		
							
								
								
									
										29
									
								
								ChangeLog
									
										
									
									
									
								
							
							
						
						
									
										29
									
								
								ChangeLog
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,13 +1,38 @@
 | 
			
		|||
Fri Mar  7 03:31:36 2003  Yukihiro Matsumoto  <matz@ruby-lang.org>
 | 
			
		||||
 | 
			
		||||
	* parse.y (dsym): :"symbol string" style should not contain `\0'.
 | 
			
		||||
 | 
			
		||||
	* process.c (proc_detach): new method Proc#detach(pid) which
 | 
			
		||||
	  create background watcher thread to issue waitpid. [new]
 | 
			
		||||
 | 
			
		||||
	* process.c (rb_detach_process): utility function to detach
 | 
			
		||||
	  process from C code.
 | 
			
		||||
 | 
			
		||||
	* ext/pty/pty.c (pty_finalize_syswait): terminate watcher thread,
 | 
			
		||||
	  and detach child process (by creating new idle waitpid watcher
 | 
			
		||||
	  thread).
 | 
			
		||||
 | 
			
		||||
	* ext/pty/pty.c (pty_syswait): may lost signal stopped child.
 | 
			
		||||
 | 
			
		||||
Fri Mar  7 00:30:33 2003  WATANABE Hirofumi  <eban@ruby-lang.org>
 | 
			
		||||
 | 
			
		||||
	* ext/Win32API/Win32API.c: no longer use inline-asms.
 | 
			
		||||
 | 
			
		||||
	* ext/Win32API/extconf.rb: no need to add gcc options.
 | 
			
		||||
 | 
			
		||||
Thu Mar  6 13:02:10 2003  Yukihiro Matsumoto  <matz@ruby-lang.org>
 | 
			
		||||
 | 
			
		||||
	* parse.y (reswords): fix reswords list.
 | 
			
		||||
 | 
			
		||||
Wed Mar  5 12:13:21 2003  WATANABE Hirofumi  <eban@ruby-lang.org>
 | 
			
		||||
 | 
			
		||||
	* configure.in: better YACC support on HP-UX.
 | 
			
		||||
 | 
			
		||||
Wed Mar  5 05:55:20 2003  Yukihiro Matsumoto  <matz@ruby-lang.org>
 | 
			
		||||
 | 
			
		||||
	* string.c (rb_str_cat): remove ptr NULL check and MEMZERO(). ptr
 | 
			
		||||
	  must be non NULL.
 | 
			
		||||
 | 
			
		||||
Tue Mar 04 23:12:07 2003  Nobuyoshi Nakada  <nobu.nokada@softhome.net>
 | 
			
		||||
 | 
			
		||||
	* configure.in, bcc32/Makefile.sub, win32/Makefile.sub: define
 | 
			
		||||
| 
						 | 
				
			
			@ -21,10 +46,10 @@ Tue Mar 04 23:12:07 2003  Nobuyoshi Nakada  <nobu.nokada@softhome.net>
 | 
			
		|||
 | 
			
		||||
Tue Mar  4 17:54:30 2003  Yukihiro Matsumoto  <matz@ruby-lang.org>
 | 
			
		||||
 | 
			
		||||
	* array.c (rb_ary_aref): give warning if index is a symbol.
 | 
			
		||||
	* array.c (rb_ary_aref): raise TypeError if index is a symbol.
 | 
			
		||||
	  [ruby-list:37217]
 | 
			
		||||
 | 
			
		||||
	* array.c (rb_ary_aset): raise TypeError if index is a symbol.
 | 
			
		||||
	* array.c (rb_ary_aset): ditto.
 | 
			
		||||
 | 
			
		||||
Tue Nov 13 14:39:11 2001  WATANABE Tetsuya  <tetsu@jpn.hp.com>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										12
									
								
								eval.c
									
										
									
									
									
								
							
							
						
						
									
										12
									
								
								eval.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -4024,17 +4024,19 @@ massign(self, node, val, pcall)
 | 
			
		|||
    int pcall;
 | 
			
		||||
{
 | 
			
		||||
    NODE *list;
 | 
			
		||||
    VALUE tmp;
 | 
			
		||||
    long i = 0, len;
 | 
			
		||||
 | 
			
		||||
    len = RARRAY(val)->len;
 | 
			
		||||
    list = node->nd_head;
 | 
			
		||||
    if (len == 1 && list) {
 | 
			
		||||
    if (len == 1 && list && (list->nd_next || node->nd_args)) {
 | 
			
		||||
	VALUE v = RARRAY(val)->ptr[0];
 | 
			
		||||
	VALUE tmp = rb_check_array_type(v);
 | 
			
		||||
	tmp = rb_check_array_type(v);
 | 
			
		||||
 | 
			
		||||
	if (NIL_P(tmp)) {
 | 
			
		||||
	    assign(self, list->nd_head, v, pcall);
 | 
			
		||||
	    list = list->nd_next;
 | 
			
		||||
	    i = 1;
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
	    len = RARRAY(tmp)->len;
 | 
			
		||||
| 
						 | 
				
			
			@ -4043,13 +4045,13 @@ massign(self, node, val, pcall)
 | 
			
		|||
		list = list->nd_next;
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
	i = 1;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
	for (; list && i<len; i++) {
 | 
			
		||||
	    assign(self, list->nd_head, RARRAY(val)->ptr[i], pcall);
 | 
			
		||||
	    list = list->nd_next;
 | 
			
		||||
	}
 | 
			
		||||
	tmp = val;
 | 
			
		||||
    }
 | 
			
		||||
    if (pcall && list) goto arg_error;
 | 
			
		||||
    if (node->nd_args) {
 | 
			
		||||
| 
						 | 
				
			
			@ -4057,7 +4059,7 @@ massign(self, node, val, pcall)
 | 
			
		|||
	    /* no check for mere `*' */
 | 
			
		||||
	}
 | 
			
		||||
	else if (!list && i<len) {
 | 
			
		||||
	    assign(self, node->nd_args, rb_ary_new4(len-i, RARRAY(val)->ptr+i), pcall);
 | 
			
		||||
	    assign(self, node->nd_args, rb_ary_new4(len-i, RARRAY(tmp)->ptr+i), pcall);
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
	    assign(self, node->nd_args, rb_ary_new2(0), pcall);
 | 
			
		||||
| 
						 | 
				
			
			@ -8640,7 +8642,7 @@ rb_thread_run(thread)
 | 
			
		|||
    return thread;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static VALUE
 | 
			
		||||
VALUE
 | 
			
		||||
rb_thread_kill(thread)
 | 
			
		||||
    VALUE thread;
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,43 +33,15 @@ following module fungtions:
 | 
			
		|||
      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.
 | 
			
		||||
 | 
			
		||||
      When the child process is suspended or finished, an exception is
 | 
			
		||||
      raised.  If this function is called with an iterator block,
 | 
			
		||||
      exception is raised only within the block.  Child process
 | 
			
		||||
      monitor is terminated on block exit.
 | 
			
		||||
 | 
			
		||||
   protect_signal
 | 
			
		||||
   reset_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.
 | 
			
		||||
 | 
			
		||||
      These functions are obsolete in this version of pty.
 | 
			
		||||
 | 
			
		||||
4. License
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -133,44 +133,50 @@ struct pty_info {
 | 
			
		|||
    VALUE thread;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
raise_from_wait(state, info)
 | 
			
		||||
    struct pty_info *info;
 | 
			
		||||
    char *state;
 | 
			
		||||
{
 | 
			
		||||
    extern VALUE rb_last_status;
 | 
			
		||||
    char buf[1024];
 | 
			
		||||
    VALUE exc;
 | 
			
		||||
 | 
			
		||||
    snprintf(buf, sizeof(buf), "pty - %s: %d", state, info->child_pid);
 | 
			
		||||
    exc = rb_exc_new2(eChildExited, buf);
 | 
			
		||||
    rb_iv_set(exc, "status", rb_last_status);
 | 
			
		||||
    rb_funcall(info->thread, rb_intern("raise"), 1, exc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static VALUE
 | 
			
		||||
pty_syswait(info)
 | 
			
		||||
    struct pty_info *info;
 | 
			
		||||
{
 | 
			
		||||
    extern VALUE rb_last_status;
 | 
			
		||||
    int cpid, status;
 | 
			
		||||
    char buf[1024];
 | 
			
		||||
    VALUE exc, st;
 | 
			
		||||
    char *state = "changed";
 | 
			
		||||
 | 
			
		||||
    cpid = rb_waitpid(info->child_pid, &status, WUNTRACED);
 | 
			
		||||
    st = rb_last_status;
 | 
			
		||||
    
 | 
			
		||||
    if (cpid == 0 || cpid == -1)
 | 
			
		||||
	return Qnil;
 | 
			
		||||
    for (;;) {
 | 
			
		||||
	cpid = rb_waitpid(info->child_pid, &status, WUNTRACED);
 | 
			
		||||
	if (cpid == -1) return Qnil;
 | 
			
		||||
 | 
			
		||||
#ifdef IF_STOPPED
 | 
			
		||||
    if (IF_STOPPED(status)) { /* suspend */
 | 
			
		||||
	state = "stopped";
 | 
			
		||||
    }
 | 
			
		||||
#else
 | 
			
		||||
#ifdef WIFSTOPPED
 | 
			
		||||
    if (WIFSTOPPED(status)) { /* suspend */
 | 
			
		||||
	state = "stopped";
 | 
			
		||||
    }
 | 
			
		||||
#if defined(IF_STOPPED)
 | 
			
		||||
	if (IF_STOPPED(status)) { /* suspend */
 | 
			
		||||
	    raise_from_wait("stopped", info);
 | 
			
		||||
	}
 | 
			
		||||
#elif defined(WIFSTOPPED)
 | 
			
		||||
	if (WIFSTOPPED(status)) { /* suspend */
 | 
			
		||||
	    raise_from_wait("stopped", info);
 | 
			
		||||
	}
 | 
			
		||||
#else
 | 
			
		||||
---->> Either IF_STOPPED or WIFSTOPPED is needed <<----
 | 
			
		||||
#endif /* WIFSTOPPED */
 | 
			
		||||
#endif /* IF_STOPPED */
 | 
			
		||||
    if (WIFEXITED(status)) {
 | 
			
		||||
	state = "exit";
 | 
			
		||||
#endif /* WIFSTOPPED | IF_STOPPED */
 | 
			
		||||
	else if (kill(info->child_pid, 0) == 0) {
 | 
			
		||||
	    raise_from_wait("changed", info);
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
	    raise_from_wait("exited", info);
 | 
			
		||||
	    return Qnil;
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    snprintf(buf, sizeof(buf), "pty - %s: %d", state, cpid);
 | 
			
		||||
    exc = rb_exc_new2(eChildExited, buf);
 | 
			
		||||
    rb_iv_set(exc, "status", st);
 | 
			
		||||
    rb_funcall(info->thread, rb_intern("raise"), 1, exc);
 | 
			
		||||
    return Qnil;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void getDevice _((int*, int*));
 | 
			
		||||
| 
						 | 
				
			
			@ -290,27 +296,14 @@ establishShell(argc, argv, info)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static VALUE
 | 
			
		||||
pty_kill_child(info)
 | 
			
		||||
pty_finalize_syswait(info)
 | 
			
		||||
    struct pty_info *info;
 | 
			
		||||
{
 | 
			
		||||
    if (rb_funcall(info->thread, rb_intern("alive?"), 0, 0) == Qtrue &&
 | 
			
		||||
	kill(info->child_pid, 0) == 0) {
 | 
			
		||||
	rb_thread_schedule();
 | 
			
		||||
	if (kill(info->child_pid, SIGTERM) == 0) {
 | 
			
		||||
	    rb_thread_schedule();
 | 
			
		||||
	    if (kill(info->child_pid, 0) == 0) {
 | 
			
		||||
		kill(info->child_pid, SIGINT);
 | 
			
		||||
		rb_thread_schedule();
 | 
			
		||||
		if (kill(info->child_pid, 0) == 0)
 | 
			
		||||
		    kill(info->child_pid, SIGKILL);
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
    rb_funcall(info->thread, rb_intern("join"), 0, 0);
 | 
			
		||||
    rb_thread_kill(info->thread);
 | 
			
		||||
    rb_detach_process(info->child_pid);
 | 
			
		||||
    return Qnil;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_OPENPTY
 | 
			
		||||
/*
 | 
			
		||||
 * Use openpty(3) of 4.3BSD Reno and later,
 | 
			
		||||
| 
						 | 
				
			
			@ -447,7 +440,7 @@ pty_getpty(argc, argv, self)
 | 
			
		|||
    thinfo.child_pid = info.child_pid;
 | 
			
		||||
 | 
			
		||||
    if (rb_block_given_p()) {
 | 
			
		||||
	rb_ensure(rb_yield, res, pty_kill_child, (VALUE)&thinfo);
 | 
			
		||||
	rb_ensure(rb_yield, res, pty_finalize_syswait, (VALUE)&thinfo);
 | 
			
		||||
	return Qnil;
 | 
			
		||||
    }
 | 
			
		||||
    return res;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,8 +10,7 @@ logfile = File.open(ofile,"a")
 | 
			
		|||
 | 
			
		||||
system "stty -echo raw lnext ^_"
 | 
			
		||||
 | 
			
		||||
PTY.spawn("/bin/csh") do
 | 
			
		||||
  |r_pty,w_pty,pid|
 | 
			
		||||
PTY.spawn("/bin/csh") do |r_pty,w_pty,pid|
 | 
			
		||||
 | 
			
		||||
  Thread.new do
 | 
			
		||||
    while true
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										1
									
								
								intern.h
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								intern.h
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -199,6 +199,7 @@ void rb_thread_sleep_forever _((void));
 | 
			
		|||
VALUE rb_thread_stop _((void));
 | 
			
		||||
VALUE rb_thread_wakeup _((VALUE));
 | 
			
		||||
VALUE rb_thread_run _((VALUE));
 | 
			
		||||
VALUE rb_thread_kill _((VALUE));
 | 
			
		||||
VALUE rb_thread_create _((VALUE (*)(ANYARGS), void*));
 | 
			
		||||
void rb_thread_interrupt _((void));
 | 
			
		||||
void rb_thread_trap_eval _((VALUE, int));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										14
									
								
								parse.y
									
										
									
									
									
								
							
							
						
						
									
										14
									
								
								parse.y
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -924,9 +924,10 @@ op		: '|'		{ $$ = '|'; }
 | 
			
		|||
reswords	: k__LINE__ | k__FILE__  | klBEGIN | klEND
 | 
			
		||||
		| kALIAS | kAND | kBEGIN | kBREAK | kCASE | kCLASS | kDEF
 | 
			
		||||
		| kDEFINED | kDO | kELSE | kELSIF | kEND | kENSURE | kFALSE
 | 
			
		||||
		| kFOR | kIF_MOD | kIN | kMODULE | kNEXT | kNIL | kNOT
 | 
			
		||||
		| kFOR | kIN | kMODULE | kNEXT | kNIL | kNOT
 | 
			
		||||
		| kOR | kREDO | kRESCUE | kRETRY | kRETURN | kSELF | kSUPER
 | 
			
		||||
		| kTHEN | kTRUE | kUNDEF | kWHEN | kYIELD
 | 
			
		||||
		| kIF_MOD | kUNLESS_MOD | kWHILE_MOD | kUNTIL_MOD | kRESCUE_MOD
 | 
			
		||||
		;
 | 
			
		||||
 | 
			
		||||
arg		: lhs '=' arg
 | 
			
		||||
| 
						 | 
				
			
			@ -2095,13 +2096,16 @@ dsym		: tSYMBEG xstring_contents tSTRING_END
 | 
			
		|||
			}
 | 
			
		||||
			else {
 | 
			
		||||
			    switch (nd_type($$)) {
 | 
			
		||||
			      case NODE_STR:
 | 
			
		||||
				$$->nd_lit = ID2SYM(rb_intern(RSTRING($$->nd_lit)->ptr));
 | 
			
		||||
				nd_set_type($$, NODE_LIT);
 | 
			
		||||
				break;
 | 
			
		||||
			      case NODE_DSTR:
 | 
			
		||||
				nd_set_type($$, NODE_DSYM);
 | 
			
		||||
				break;
 | 
			
		||||
			      case NODE_STR:
 | 
			
		||||
				if (strlen(RSTRING($$->nd_lit)->ptr) == RSTRING($$->nd_lit)->len) {
 | 
			
		||||
				    $$->nd_lit = ID2SYM(rb_intern(RSTRING($$->nd_lit)->ptr));
 | 
			
		||||
				    nd_set_type($$, NODE_LIT);
 | 
			
		||||
				    break;
 | 
			
		||||
				}
 | 
			
		||||
				/* fall through */
 | 
			
		||||
			      default:
 | 
			
		||||
				$$ = rb_node_newnode(NODE_DSYM, rb_str_new(0, 0),
 | 
			
		||||
						     1, NEW_LIST($$));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										28
									
								
								process.c
									
										
									
									
									
								
							
							
						
						
									
										28
									
								
								process.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -411,6 +411,33 @@ proc_waitall()
 | 
			
		|||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static VALUE
 | 
			
		||||
detach_process_watcer(pid_p)
 | 
			
		||||
    int *pid_p;
 | 
			
		||||
{
 | 
			
		||||
    int cpid, status;
 | 
			
		||||
 | 
			
		||||
    for (;;) {
 | 
			
		||||
	cpid = rb_waitpid(*pid_p, &status, WNOHANG);
 | 
			
		||||
	if (cpid == -1) return Qnil;
 | 
			
		||||
	rb_thread_sleep(1);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
rb_detach_process(pid)
 | 
			
		||||
    int pid;
 | 
			
		||||
{
 | 
			
		||||
    rb_thread_create(detach_process_watcer, (void*)&pid);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static VALUE
 | 
			
		||||
proc_detach(obj, pid)
 | 
			
		||||
    VALUE pid;
 | 
			
		||||
{
 | 
			
		||||
    rb_detach_process(NUM2INT(pid));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifndef HAVE_STRING_H
 | 
			
		||||
char *strtok();
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1319,6 +1346,7 @@ Init_process()
 | 
			
		|||
    rb_define_module_function(rb_mProcess, "waitpid", proc_wait, -1);
 | 
			
		||||
    rb_define_module_function(rb_mProcess, "waitpid2", proc_wait2, -1);
 | 
			
		||||
    rb_define_module_function(rb_mProcess, "waitall", proc_waitall, 0);
 | 
			
		||||
    rb_define_module_function(rb_mProcess, "detach", proc_detach, 1);
 | 
			
		||||
 | 
			
		||||
    rb_cProcStatus = rb_define_class_under(rb_mProcess, "Status", rb_cObject);
 | 
			
		||||
    rb_undef_method(CLASS_OF(rb_cProcStatus), "new");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										9
									
								
								string.c
									
										
									
									
									
								
							
							
						
						
									
										9
									
								
								string.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -614,12 +614,7 @@ rb_str_cat(str, ptr, len)
 | 
			
		|||
    if (FL_TEST(str, STR_ASSOC)) {
 | 
			
		||||
	rb_str_modify(str);
 | 
			
		||||
	REALLOC_N(RSTRING(str)->ptr, char, RSTRING(str)->len+len);
 | 
			
		||||
	if (ptr) {
 | 
			
		||||
	    memcpy(RSTRING(str)->ptr + RSTRING(str)->len, ptr, len);
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
	    MEMZERO(RSTRING(str)->ptr + RSTRING(str)->len, char, len);
 | 
			
		||||
	}
 | 
			
		||||
	memcpy(RSTRING(str)->ptr + RSTRING(str)->len, ptr, len);
 | 
			
		||||
	RSTRING(str)->len += len;
 | 
			
		||||
	RSTRING(str)->ptr[RSTRING(str)->len] = '\0'; /* sentinel */
 | 
			
		||||
	return str;
 | 
			
		||||
| 
						 | 
				
			
			@ -3076,7 +3071,7 @@ rb_str_intern(str)
 | 
			
		|||
	rb_raise(rb_eArgError, "interning empty string");
 | 
			
		||||
    }
 | 
			
		||||
    if (strlen(RSTRING(str)->ptr) != RSTRING(str)->len)
 | 
			
		||||
	rb_raise(rb_eArgError, "string contains `\\0'");
 | 
			
		||||
	rb_raise(rb_eArgError, "symbol string may not contain `\\0'");
 | 
			
		||||
    id = rb_intern(RSTRING(str)->ptr);
 | 
			
		||||
    return ID2SYM(id);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue