summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--ext/socket/socket.c150
-rw-r--r--misc/ruby-mode.el314
3 files changed, 202 insertions, 267 deletions
diff --git a/ChangeLog b/ChangeLog
index c6f6bb7257..3a2aa1a261 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
diff --git a/ext/socket/socket.c b/ext/socket/socket.c
index 3bbc5fc8ea..d13f6484ae 100644
--- a/ext/socket/socket.c
+++ b/ext/socket/socket.c
@@ -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));
@@ -529,15 +497,6 @@ bsock_do_not_rev_lookup_set(self, 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;
char *buf;
@@ -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);
diff --git a/misc/ruby-mode.el b/misc/ruby-mode.el
index dac90ee1a2..1972003059 100644
--- a/misc/ruby-mode.el
+++ b/misc/ruby-mode.el
@@ -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)
+ (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)
+ (if (re-search-forward "^\\s *#" end t)
+ (beginning-of-line)
+ (setq done t))))
+ (setq bol (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 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")
- (let (end (pos (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)))
+ (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")