mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* ext/socket/socket.c (make_hostent): fix memory leak, based on
the patch from HORIKAWA Hisashi <vzw00011@nifty.ne.jp>. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@6065 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
b9e7165e78
commit
64ec09d456
3 changed files with 203 additions and 268 deletions
|
@ -1,3 +1,8 @@
|
|||
Fri Apr 2 07:31:38 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||
|
||||
* ext/socket/socket.c (make_hostent): fix memory leak, based on
|
||||
the patch from HORIKAWA Hisashi <vzw00011@nifty.ne.jp>.
|
||||
|
||||
Thu Apr 1 19:58:37 2004 NAKAMURA, Hiroshi <nakahiro@sarion.co.jp>
|
||||
|
||||
* lib/soap/mapping/{factory.rb,registry.rb}: fixed illegal mapped URI
|
||||
|
|
|
@ -65,7 +65,6 @@
|
|||
#include "sockport.h"
|
||||
|
||||
static int do_not_reverse_lookup = 0;
|
||||
#define FMODE_NOREVLOOKUP 0x100
|
||||
|
||||
VALUE rb_cBasicSocket;
|
||||
VALUE rb_cIPSocket;
|
||||
|
@ -179,9 +178,6 @@ init_sock(sock, fd)
|
|||
fp->f = rb_fdopen(fd, "r");
|
||||
fp->f2 = rb_fdopen(fd, "w");
|
||||
fp->mode = FMODE_READWRITE;
|
||||
if (do_not_reverse_lookup) {
|
||||
fp->mode |= FMODE_NOREVLOOKUP;
|
||||
}
|
||||
rb_io_synchronized(fp);
|
||||
|
||||
return sock;
|
||||
|
@ -396,35 +392,7 @@ bsock_send(argc, argv, sock)
|
|||
return INT2FIX(n);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
bsock_do_not_reverse_lookup(sock)
|
||||
VALUE sock;
|
||||
{
|
||||
OpenFile *fptr;
|
||||
|
||||
GetOpenFile(sock, fptr);
|
||||
return (fptr->mode & FMODE_NOREVLOOKUP) ? Qtrue : Qfalse;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
bsock_do_not_reverse_lookup_set(sock, state)
|
||||
VALUE sock;
|
||||
VALUE state;
|
||||
{
|
||||
OpenFile *fptr;
|
||||
|
||||
rb_secure(4);
|
||||
GetOpenFile(sock, fptr);
|
||||
if (RTEST(state)) {
|
||||
fptr->mode |= FMODE_NOREVLOOKUP;
|
||||
}
|
||||
else {
|
||||
fptr->mode &= ~FMODE_NOREVLOOKUP;
|
||||
}
|
||||
return sock;
|
||||
}
|
||||
|
||||
static VALUE ipaddr _((struct sockaddr*, int));
|
||||
static VALUE ipaddr _((struct sockaddr*));
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
static VALUE unixaddr _((struct sockaddr_un*));
|
||||
#endif
|
||||
|
@ -492,7 +460,7 @@ s_recvfrom(sock, argc, argv, from)
|
|||
rb_raise(rb_eTypeError, "sockaddr size differs - should not happen");
|
||||
}
|
||||
#endif
|
||||
return rb_assoc_new(str, ipaddr((struct sockaddr*)buf, fptr->mode & FMODE_NOREVLOOKUP));
|
||||
return rb_assoc_new(str, ipaddr((struct sockaddr*)buf));
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
case RECV_UNIX:
|
||||
return rb_assoc_new(str, unixaddr((struct sockaddr_un*)buf));
|
||||
|
@ -528,15 +496,6 @@ bsock_do_not_rev_lookup_set(self, val)
|
|||
return val;
|
||||
}
|
||||
|
||||
static void
|
||||
raise_socket_error(reason, error)
|
||||
char *reason;
|
||||
int error;
|
||||
{
|
||||
if (error == EAI_SYSTEM) rb_sys_fail(reason);
|
||||
rb_raise(rb_eSocket, "%s: %s", reason, gai_strerror(error));
|
||||
}
|
||||
|
||||
static void
|
||||
make_ipaddr0(addr, buf, len)
|
||||
struct sockaddr *addr;
|
||||
|
@ -547,7 +506,7 @@ make_ipaddr0(addr, buf, len)
|
|||
|
||||
error = getnameinfo(addr, SA_LEN(addr), buf, len, NULL, 0, NI_NUMERICHOST);
|
||||
if (error) {
|
||||
raise_socket_error("getnameinfo", error);
|
||||
rb_raise(rb_eSocket, "getnameinfo: %s", gai_strerror(error));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -666,7 +625,8 @@ sock_addrinfo(host, port, socktype, flags)
|
|||
VALUE host, port;
|
||||
int socktype, flags;
|
||||
{
|
||||
struct addrinfo hints, *hintsp, *res;
|
||||
struct addrinfo hints;
|
||||
struct addrinfo* res = NULL;
|
||||
char *hostp, *portp;
|
||||
int error;
|
||||
char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
|
||||
|
@ -678,18 +638,16 @@ sock_addrinfo(host, port, socktype, flags)
|
|||
socktype = SOCK_DGRAM;
|
||||
}
|
||||
|
||||
hintsp = &hints;
|
||||
MEMZERO(&hints, struct addrinfo, 1);
|
||||
hints.ai_family = PF_UNSPEC;
|
||||
hints.ai_protocol = 0;
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = socktype;
|
||||
hints.ai_flags = flags;
|
||||
error = getaddrinfo(hostp, portp, hintsp, &res);
|
||||
error = getaddrinfo(hostp, portp, &hints, &res);
|
||||
if (error) {
|
||||
if (hostp && hostp[strlen(hostp)-1] == '\n') {
|
||||
rb_raise(rb_eSocket, "newline at the end of hostname");
|
||||
}
|
||||
raise_socket_error("getaddrinfo", error);
|
||||
rb_raise(rb_eSocket, "getaddrinfo: %s", gai_strerror(error));
|
||||
}
|
||||
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
|
@ -713,9 +671,8 @@ sock_addrinfo(host, port, socktype, flags)
|
|||
}
|
||||
|
||||
static VALUE
|
||||
ipaddr(sockaddr, norevlookup)
|
||||
ipaddr(sockaddr)
|
||||
struct sockaddr *sockaddr;
|
||||
int norevlookup;
|
||||
{
|
||||
VALUE family, port, addr1, addr2;
|
||||
VALUE ary;
|
||||
|
@ -748,22 +705,21 @@ ipaddr(sockaddr, norevlookup)
|
|||
family = rb_str_new2(pbuf);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!norevlookup) {
|
||||
if (!do_not_reverse_lookup) {
|
||||
error = getnameinfo(sockaddr, SA_LEN(sockaddr), hbuf, sizeof(hbuf),
|
||||
NULL, 0, 0);
|
||||
if (error) {
|
||||
raise_socket_error("getnameinfo", error);
|
||||
rb_raise(rb_eSocket, "getnameinfo: %s", gai_strerror(error));
|
||||
}
|
||||
addr1 = rb_str_new2(hbuf);
|
||||
}
|
||||
error = getnameinfo(sockaddr, SA_LEN(sockaddr), hbuf, sizeof(hbuf),
|
||||
pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV);
|
||||
if (error) {
|
||||
raise_socket_error("getnameinfo", error);
|
||||
rb_raise(rb_eSocket, "getnameinfo: %s", gai_strerror(error));
|
||||
}
|
||||
addr2 = rb_str_new2(hbuf);
|
||||
if (norevlookup) {
|
||||
if (do_not_reverse_lookup) {
|
||||
addr1 = addr2;
|
||||
}
|
||||
port = INT2FIX(atoi(pbuf));
|
||||
|
@ -1086,48 +1042,43 @@ socks_s_close(sock)
|
|||
#endif
|
||||
#endif
|
||||
|
||||
static VALUE
|
||||
sock_gethostbyname(host, ipaddr)
|
||||
struct hostent_arg {
|
||||
VALUE host;
|
||||
VALUE (*ipaddr) _((struct sockaddr*, size_t));
|
||||
struct addrinfo* addr;
|
||||
VALUE (*ipaddr)_((struct sockaddr*, size_t));
|
||||
};
|
||||
|
||||
static VALUE
|
||||
make_hostent_internal(arg)
|
||||
struct hostent_arg *arg;
|
||||
{
|
||||
struct addrinfo *addr;
|
||||
VALUE host = arg->host;
|
||||
struct addrinfo* addr = arg->addr;
|
||||
VALUE (*ipaddr)_((struct sockaddr*, size_t)) = arg->ipaddr;
|
||||
|
||||
struct addrinfo *ai;
|
||||
struct hostent *h;
|
||||
VALUE ary, names;
|
||||
char *hostname;
|
||||
char **pch;
|
||||
const char* hostp;
|
||||
char hbuf[NI_MAXHOST];
|
||||
|
||||
addr = sock_addrinfo(host, Qnil, SOCK_STREAM, AI_CANONNAME);
|
||||
ary = rb_ary_new();
|
||||
if (addr->ai_canonname) {
|
||||
hostname = addr->ai_canonname;
|
||||
hostp = addr->ai_canonname;
|
||||
}
|
||||
else {
|
||||
hostname = StringValuePtr(host);
|
||||
hostp = host_str(host, hbuf, sizeof(hbuf));
|
||||
}
|
||||
rb_ary_push(ary, rb_str_new2(hostname));
|
||||
#if defined(HAVE_GETIPNODEBYNAME)
|
||||
{
|
||||
int error;
|
||||
rb_ary_push(ary, rb_str_new2(hostp));
|
||||
|
||||
h = getipnodebyname(hostname, addr->ai_family, AI_ALL, &error);
|
||||
}
|
||||
#elif defined(HAVE_GETHOSTBYNAME2)
|
||||
h = gethostbyname2(hostname, addr->ai_family);
|
||||
#else
|
||||
h = gethostbyname(hostname);
|
||||
#endif
|
||||
if (h) {
|
||||
if (addr->ai_canonname && (h = gethostbyname(addr->ai_canonname))) {
|
||||
names = rb_ary_new();
|
||||
if (h->h_aliases != NULL) {
|
||||
for (pch = h->h_aliases; *pch; pch++) {
|
||||
rb_ary_push(names, rb_str_new2(*pch));
|
||||
}
|
||||
}
|
||||
#if defined(HAVE_GETIPNODEBYNAME)
|
||||
freehostent(h);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
names = rb_ary_new2(0);
|
||||
|
@ -1141,6 +1092,22 @@ sock_gethostbyname(host, ipaddr)
|
|||
return ary;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
make_hostent(host, addr, ipaddr)
|
||||
VALUE host;
|
||||
struct addrinfo* addr;
|
||||
VALUE (*ipaddr)_((struct sockaddr*, size_t));
|
||||
{
|
||||
VALUE ary;
|
||||
struct hostent_arg arg;
|
||||
|
||||
arg.host = host;
|
||||
arg.addr = addr;
|
||||
arg.ipaddr = ipaddr;
|
||||
ary = rb_ensure(make_hostent_internal, (VALUE)&arg,
|
||||
RUBY_METHOD_FUNC(freeaddrinfo), (VALUE)addr);
|
||||
}
|
||||
|
||||
VALUE
|
||||
tcp_sockaddr(addr, len)
|
||||
struct sockaddr *addr;
|
||||
|
@ -1154,7 +1121,7 @@ tcp_s_gethostbyname(obj, host)
|
|||
VALUE obj, host;
|
||||
{
|
||||
rb_secure(3);
|
||||
return sock_gethostbyname(host, tcp_sockaddr);
|
||||
return make_hostent(host, sock_addrinfo(host, Qnil, SOCK_STREAM, AI_CANONNAME), tcp_sockaddr);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
|
@ -1314,7 +1281,7 @@ ip_addr(sock)
|
|||
|
||||
if (getsockname(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0)
|
||||
rb_sys_fail("getsockname(2)");
|
||||
return ipaddr((struct sockaddr*)&addr, fptr->mode & FMODE_NOREVLOOKUP);
|
||||
return ipaddr((struct sockaddr*)&addr);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
|
@ -1329,7 +1296,7 @@ ip_peeraddr(sock)
|
|||
|
||||
if (getpeername(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0)
|
||||
rb_sys_fail("getpeername(2)");
|
||||
return ipaddr((struct sockaddr*)&addr, fptr->mode & FMODE_NOREVLOOKUP);
|
||||
return ipaddr((struct sockaddr*)&addr);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
|
@ -1715,7 +1682,6 @@ unix_sysaccept(sock)
|
|||
return s_accept(0, fileno(fptr->f), (struct sockaddr*)&from, &fromlen);
|
||||
}
|
||||
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
static VALUE
|
||||
unixaddr(sockaddr)
|
||||
struct sockaddr_un *sockaddr;
|
||||
|
@ -1723,7 +1689,6 @@ unixaddr(sockaddr)
|
|||
return rb_assoc_new(rb_str_new2("AF_UNIX"),
|
||||
rb_str_new2(sockaddr->sun_path));
|
||||
}
|
||||
#endif
|
||||
|
||||
static VALUE
|
||||
unix_addr(sock)
|
||||
|
@ -2045,10 +2010,7 @@ make_addrinfo(res0)
|
|||
}
|
||||
base = rb_ary_new();
|
||||
for (res = res0; res; res = res->ai_next) {
|
||||
ary = ipaddr(res->ai_addr, do_not_reverse_lookup);
|
||||
if (res->ai_canonname) {
|
||||
RARRAY(ary)->ptr[2] = rb_str_new2(res->ai_canonname);
|
||||
}
|
||||
ary = ipaddr(res->ai_addr);
|
||||
rb_ary_push(ary, INT2FIX(res->ai_family));
|
||||
rb_ary_push(ary, INT2FIX(res->ai_socktype));
|
||||
rb_ary_push(ary, INT2FIX(res->ai_protocol));
|
||||
|
@ -2070,7 +2032,7 @@ sock_s_gethostbyname(obj, host)
|
|||
VALUE obj, host;
|
||||
{
|
||||
rb_secure(3);
|
||||
return sock_gethostbyname(host, sock_sockaddr);
|
||||
return make_hostent(host, sock_addrinfo(host, Qnil, SOCK_STREAM, AI_CANONNAME), sock_sockaddr);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
|
@ -2219,7 +2181,7 @@ sock_s_getaddrinfo(argc, argv)
|
|||
}
|
||||
error = getaddrinfo(hptr, pptr, &hints, &res);
|
||||
if (error) {
|
||||
raise_socket_error("getaddrinfo", error);
|
||||
rb_raise(rb_eSocket, "getaddrinfo: %s", gai_strerror(error));
|
||||
}
|
||||
|
||||
ret = make_addrinfo(res);
|
||||
|
@ -2356,11 +2318,11 @@ sock_s_getnameinfo(argc, argv)
|
|||
|
||||
error_exit_addr:
|
||||
if (res) freeaddrinfo(res);
|
||||
raise_socket_error("getaddrinfo", error);
|
||||
rb_raise(rb_eSocket, "getaddrinfo: %s", gai_strerror(error));
|
||||
|
||||
error_exit_name:
|
||||
if (res) freeaddrinfo(res);
|
||||
raise_socket_error("getnameinfo", error);
|
||||
rb_raise(rb_eSocket, "getnameinfo: %s", gai_strerror(error));
|
||||
}
|
||||
|
||||
static VALUE
|
||||
|
@ -2460,8 +2422,6 @@ Init_socket()
|
|||
rb_define_method(rb_cBasicSocket, "getpeername", bsock_getpeername, 0);
|
||||
rb_define_method(rb_cBasicSocket, "send", bsock_send, -1);
|
||||
rb_define_method(rb_cBasicSocket, "recv", bsock_recv, -1);
|
||||
rb_define_method(rb_cBasicSocket, "do_not_reverse_lookup", bsock_do_not_reverse_lookup, 0);
|
||||
rb_define_method(rb_cBasicSocket, "do_not_reverse_lookup=", bsock_do_not_reverse_lookup_set, 1);
|
||||
|
||||
rb_cIPSocket = rb_define_class("IPSocket", rb_cBasicSocket);
|
||||
rb_define_global_const("IPsocket", rb_cIPSocket);
|
||||
|
|
|
@ -561,186 +561,156 @@ The variable ruby-indent-level controls the amount of indentation.
|
|||
(defun ruby-indent-size (pos nest)
|
||||
(+ pos (* (or nest 1) ruby-indent-level)))
|
||||
|
||||
;;; maybe obsolete
|
||||
(defconst ruby-assign-re "\\s *\\(&&\\|||\\|<<\\|>>\\|[-+*/%&|^]\\)?=\\s *")
|
||||
|
||||
;;; maybe obsolete
|
||||
(defun ruby-beginning-of-arg (start end)
|
||||
(save-restriction
|
||||
(narrow-to-region start (1+ end))
|
||||
(goto-char start)
|
||||
(let ((beg t) arg)
|
||||
(while
|
||||
(progn
|
||||
(skip-chars-forward " \t\n")
|
||||
(and (not (eobp))
|
||||
(= (ruby-forward-sexp) 0)))
|
||||
(skip-syntax-forward " ")
|
||||
(cond ((looking-at ",")
|
||||
(forward-char)
|
||||
(setq arg start beg t))
|
||||
((ruby-expr-beg) t)
|
||||
((looking-at "=>\\s *")
|
||||
(goto-char (match-end 0))
|
||||
(setq arg nil beg nil))
|
||||
((looking-at ruby-assign-re)
|
||||
(goto-char (match-end 0))
|
||||
(if beg (setq beg nil arg (point))))
|
||||
((looking-at ruby-operator-re)
|
||||
(goto-char (match-end 0))
|
||||
(echo "foo %s %s" arg beg)
|
||||
(if beg (setq beg nil arg (match-end 0))))
|
||||
((not (eq (char-syntax (char-after)) ?\())
|
||||
(setq start (point)))))
|
||||
(goto-char (or arg start)))))
|
||||
|
||||
(defun ruby-calculate-indent (&optional parse-start)
|
||||
(save-excursion
|
||||
(beginning-of-line)
|
||||
(let ((indent-point (point))
|
||||
(case-fold-search nil)
|
||||
state bol eol begin
|
||||
(paren (progn (skip-syntax-forward " ")
|
||||
(and (char-after) (matching-paren (char-after)))))
|
||||
(indent 0))
|
||||
(if parse-start
|
||||
(goto-char parse-start)
|
||||
(ruby-beginning-of-indent)
|
||||
(setq parse-start (point)))
|
||||
(back-to-indentation)
|
||||
(setq indent (current-column))
|
||||
(setq state (ruby-parse-region parse-start indent-point))
|
||||
(cond
|
||||
((nth 0 state) ; within string
|
||||
(setq indent nil)) ; do nothing
|
||||
((car (nth 1 state)) ; in paren
|
||||
(goto-char (setq begin (cdr (nth 1 state))))
|
||||
(let ((deep (ruby-deep-indent-paren-p (car (nth 1 state)))))
|
||||
(if deep
|
||||
(cond ((and (eq deep t) (eq (car (nth 1 state)) paren))
|
||||
(skip-syntax-backward " ")
|
||||
(setq indent (1- (current-column))))
|
||||
((let ((s (ruby-parse-region (point) indent-point)))
|
||||
(and (nth 2 s) (> (nth 2 s) 0)
|
||||
(or (goto-char (cdr (nth 1 s))) t)))
|
||||
(forward-word -1)
|
||||
(setq indent (ruby-indent-size (current-column) (nth 2 state))))
|
||||
(t
|
||||
(setq indent (current-column))
|
||||
(cond ((eq deep 'space))
|
||||
(paren (setq indent (1- indent)))
|
||||
(t (setq indent (ruby-indent-size (1- indent) 1))))))
|
||||
(if (nth 3 state) (goto-char (nth 3 state))
|
||||
(goto-char parse-start) (back-to-indentation))
|
||||
(setq indent (ruby-indent-size (current-column) (nth 2 state))))))
|
||||
((and (nth 2 state) (> (nth 2 state) 0)) ; in nest
|
||||
(if (null (cdr (nth 1 state)))
|
||||
(error "invalid nest"))
|
||||
(goto-char (cdr (nth 1 state)))
|
||||
(forward-word -1) ; skip back a keyword
|
||||
(setq begin (point))
|
||||
(cond
|
||||
((looking-at "do\\>[^_]") ; iter block is a special case
|
||||
(case-fold-search nil)
|
||||
state bol eol begin op-end
|
||||
(paren (progn (skip-syntax-forward " ")
|
||||
(and (char-after) (matching-paren (char-after)))))
|
||||
(indent 0))
|
||||
(if parse-start
|
||||
(goto-char parse-start)
|
||||
(ruby-beginning-of-indent)
|
||||
(setq parse-start (point)))
|
||||
(back-to-indentation)
|
||||
(setq indent (current-column))
|
||||
(setq state (ruby-parse-region parse-start indent-point))
|
||||
(cond
|
||||
((nth 0 state) ; within string
|
||||
(setq indent nil)) ; do nothing
|
||||
((car (nth 1 state)) ; in paren
|
||||
(goto-char (setq begin (cdr (nth 1 state))))
|
||||
(let ((deep (ruby-deep-indent-paren-p (car (nth 1 state)))))
|
||||
(if deep
|
||||
(cond ((and (eq deep t) (eq (car (nth 1 state)) paren))
|
||||
(skip-syntax-backward " ")
|
||||
(setq indent (1- (current-column))))
|
||||
((let ((s (ruby-parse-region (point) indent-point)))
|
||||
(and (nth 2 s) (> (nth 2 s) 0)
|
||||
(or (goto-char (cdr (nth 1 s))) t)))
|
||||
(forward-word -1)
|
||||
(setq indent (ruby-indent-size (current-column) (nth 2 state))))
|
||||
(t
|
||||
(setq indent (current-column))
|
||||
(cond ((eq deep 'space))
|
||||
(paren (setq indent (1- indent)))
|
||||
(t (setq indent (ruby-indent-size (1- indent) 1))))))
|
||||
(if (nth 3 state) (goto-char (nth 3 state))
|
||||
(goto-char parse-start) (back-to-indentation))
|
||||
(setq indent (ruby-indent-size (current-column) (nth 2 state))))
|
||||
(t
|
||||
(setq indent (+ (current-column) ruby-indent-level)))))
|
||||
|
||||
((and (nth 2 state) (< (nth 2 state) 0)) ; in negative nest
|
||||
(setq indent (ruby-indent-size (current-column) (nth 2 state)))))
|
||||
(when indent
|
||||
(goto-char indent-point)
|
||||
(end-of-line)
|
||||
(setq eol (point))
|
||||
(beginning-of-line)
|
||||
(cond
|
||||
((and (not (ruby-deep-indent-paren-p paren))
|
||||
(re-search-forward ruby-negative eol t))
|
||||
(and (not (eq ?_ (char-after (match-end 0))))
|
||||
(setq indent (- indent ruby-indent-level))))
|
||||
;;operator terminated lines
|
||||
((and
|
||||
(save-excursion
|
||||
(beginning-of-line)
|
||||
(not (bobp)))
|
||||
(or (ruby-deep-indent-paren-p t)
|
||||
(null (car (nth 1 state)))))
|
||||
;; goto beginning of non-empty no-comment line
|
||||
(let (end done)
|
||||
(while (not done)
|
||||
(skip-chars-backward " \t\n")
|
||||
(setq end (point))
|
||||
(beginning-of-line)
|
||||
(if (re-search-forward "^\\s *#" end t)
|
||||
(beginning-of-line)
|
||||
(setq done t))))
|
||||
(setq bol (point))
|
||||
(end-of-line)
|
||||
(skip-chars-backward " \t")
|
||||
(let (end (pos (point)))
|
||||
(setq indent (ruby-indent-size (current-column) (nth 2 state))))))
|
||||
((and (nth 2 state) (> (nth 2 state) 0)) ; in nest
|
||||
(if (null (cdr (nth 1 state)))
|
||||
(error "invalid nest"))
|
||||
(goto-char (cdr (nth 1 state)))
|
||||
(forward-word -1) ; skip back a keyword
|
||||
(setq begin (point))
|
||||
(cond
|
||||
((looking-at "do\\>[^_]") ; iter block is a special case
|
||||
(if (nth 3 state) (goto-char (nth 3 state))
|
||||
(goto-char parse-start) (back-to-indentation))
|
||||
(setq indent (ruby-indent-size (current-column) (nth 2 state))))
|
||||
(t
|
||||
(setq indent (+ (current-column) ruby-indent-level)))))
|
||||
|
||||
((and (nth 2 state) (< (nth 2 state) 0)) ; in negative nest
|
||||
(setq indent (ruby-indent-size (current-column) (nth 2 state)))))
|
||||
(when indent
|
||||
(goto-char indent-point)
|
||||
(end-of-line)
|
||||
(setq eol (point))
|
||||
(beginning-of-line)
|
||||
(cond
|
||||
((and (not (ruby-deep-indent-paren-p paren))
|
||||
(re-search-forward ruby-negative eol t))
|
||||
(and (not (eq ?_ (char-after (match-end 0))))
|
||||
(setq indent (- indent ruby-indent-level))))
|
||||
((and
|
||||
(save-excursion
|
||||
(beginning-of-line)
|
||||
(not (bobp)))
|
||||
(or (ruby-deep-indent-paren-p t)
|
||||
(null (car (nth 1 state)))))
|
||||
;; goto beginning of non-empty no-comment line
|
||||
(let (end done)
|
||||
(while (not done)
|
||||
(skip-chars-backward " \t\n")
|
||||
(setq end (point))
|
||||
(beginning-of-line)
|
||||
(while (and (re-search-forward "#" pos t)
|
||||
(setq end (1- (point)))
|
||||
(ruby-special-char-p end))
|
||||
(setq end nil))
|
||||
(goto-char (or end pos))
|
||||
(skip-chars-backward " \t")
|
||||
(setq state (ruby-parse-region parse-start (point)))
|
||||
(setq begin (or (nth 0 state) (cdr (nth 1 state))))
|
||||
(goto-char pos))
|
||||
(or (bobp) (forward-char -1))
|
||||
(and
|
||||
(or (and (looking-at ruby-symbol-re)
|
||||
(skip-chars-backward ruby-symbol-chars)
|
||||
(looking-at ruby-block-hanging-re)
|
||||
(not (eq (point) (nth 3 state)))
|
||||
(save-excursion
|
||||
(goto-char (match-end 0))
|
||||
(not (looking-at "[a-z_]"))))
|
||||
(and (looking-at ruby-operator-re)
|
||||
(not (ruby-special-char-p))
|
||||
(let ((c (char-after (point))))
|
||||
(and
|
||||
(or (not (eq ?, c))
|
||||
(null begin)
|
||||
(save-excursion
|
||||
(goto-char begin)
|
||||
(skip-chars-forward " \t")
|
||||
(not (or (eolp) (looking-at "#")
|
||||
(and (eq (car (nth 1 state)) ?{)
|
||||
(looking-at "|"))))))
|
||||
(or (not (eq ?/ c))
|
||||
(null (nth 0 (ruby-parse-region (or begin parse-start) (point)))))
|
||||
(or (not (eq ?| (char-after (point))))
|
||||
(save-excursion
|
||||
(or (eolp) (forward-char -1))
|
||||
(cond
|
||||
((search-backward "|" nil t)
|
||||
(skip-chars-backward " \t\n")
|
||||
(and (not (eolp))
|
||||
(progn
|
||||
(forward-char -1)
|
||||
(not (looking-at "{")))
|
||||
(progn
|
||||
(forward-word -1)
|
||||
(not (looking-at "do\\>[^_]")))))
|
||||
(t t))))))))
|
||||
(setq indent
|
||||
(cond
|
||||
((and
|
||||
(not (looking-at ruby-block-hanging-re))
|
||||
(eq (ruby-deep-indent-paren-p t) 'space)
|
||||
(not (bobp)))
|
||||
(save-excursion
|
||||
(widen)
|
||||
(goto-char (or begin parse-start))
|
||||
(skip-syntax-forward " ")
|
||||
;; (ruby-beginning-of-arg (or begin parse-start) (point))
|
||||
(current-column)))
|
||||
(t
|
||||
(+ indent ruby-indent-level))))))))
|
||||
indent)))
|
||||
(if (re-search-forward "^\\s *#" end t)
|
||||
(beginning-of-line)
|
||||
(setq done t))))
|
||||
(setq bol (point))
|
||||
(end-of-line)
|
||||
;; skip the comment at the end
|
||||
(skip-chars-backward " \t")
|
||||
(let (end (pos (point)))
|
||||
(beginning-of-line)
|
||||
(while (and (re-search-forward "#" pos t)
|
||||
(setq end (1- (point)))
|
||||
(or (ruby-special-char-p end)
|
||||
(and (setq state (ruby-parse-region parse-start end))
|
||||
(nth 0 state))))
|
||||
(setq end nil))
|
||||
(goto-char (or end pos))
|
||||
(skip-chars-backward " \t")
|
||||
(setq begin (if (nth 0 state) pos (cdr (nth 1 state))))
|
||||
(setq state (ruby-parse-region parse-start (point))))
|
||||
(or (bobp) (forward-char -1))
|
||||
(and
|
||||
(or (and (looking-at ruby-symbol-re)
|
||||
(skip-chars-backward ruby-symbol-chars)
|
||||
(looking-at ruby-block-hanging-re)
|
||||
(not (eq (point) (nth 3 state)))
|
||||
(save-excursion
|
||||
(goto-char (match-end 0))
|
||||
(not (looking-at "[a-z_]"))))
|
||||
(and (looking-at ruby-operator-re)
|
||||
(not (ruby-special-char-p))
|
||||
;; operator at the end of line
|
||||
(let ((c (char-after (point))))
|
||||
(and
|
||||
;; (or (null begin)
|
||||
;; (save-excursion
|
||||
;; (goto-char begin)
|
||||
;; (skip-chars-forward " \t")
|
||||
;; (not (or (eolp) (looking-at "#")
|
||||
;; (and (eq (car (nth 1 state)) ?{)
|
||||
;; (looking-at "|"))))))
|
||||
(or (not (eq ?/ c))
|
||||
(null (nth 0 (ruby-parse-region (or begin parse-start) (point)))))
|
||||
(or (not (eq ?| (char-after (point))))
|
||||
(save-excursion
|
||||
(or (eolp) (forward-char -1))
|
||||
(cond
|
||||
((search-backward "|" nil t)
|
||||
(skip-chars-backward " \t\n")
|
||||
(and (not (eolp))
|
||||
(progn
|
||||
(forward-char -1)
|
||||
(not (looking-at "{")))
|
||||
(progn
|
||||
(forward-word -1)
|
||||
(not (looking-at "do\\>[^_]")))))
|
||||
(t t))))
|
||||
(not (eq ?, c))
|
||||
(setq op-end t)))))
|
||||
(setq indent
|
||||
(cond
|
||||
((and
|
||||
(null op-end)
|
||||
(not (looking-at ruby-block-hanging-re))
|
||||
(eq (ruby-deep-indent-paren-p t) 'space)
|
||||
(not (bobp)))
|
||||
(save-excursion
|
||||
(widen)
|
||||
(goto-char (or begin parse-start))
|
||||
(skip-syntax-forward " ")
|
||||
(current-column)))
|
||||
(t
|
||||
(+ indent ruby-indent-level))))))))
|
||||
indent)))
|
||||
|
||||
(defun ruby-electric-brace (arg)
|
||||
(interactive "P")
|
||||
|
|
Loading…
Reference in a new issue