From: nobu.nokada@... Date: 2005-05-12T09:21:31+09:00 Subject: Re: Encoding Pragma Hi, At Thu, 12 May 2005 08:03:48 +0900, Bertram Scharpf wrote in [ruby-core:04881]: > Why don't I retrieve the UTF-8 answer in the first case? Although ruby doesn't have pragma right now, I'm using this patch. Index: intern.h =================================================================== RCS file: /cvs/ruby/src/ruby/intern.h,v retrieving revision 1.166 diff -U2 -p -r1.166 intern.h --- intern.h 19 Apr 2005 14:02:48 -0000 1.166 +++ intern.h 19 Apr 2005 15:42:23 -0000 @@ -395,4 +395,5 @@ void ruby_load_script _((void)); void ruby_init_loadpath _((void)); void ruby_incpush _((const char*)); +void ruby_modeset _((const char*, int)); /* signal.c */ VALUE rb_f_kill _((int, VALUE*)); Index: parse.y =================================================================== RCS file: /cvs/ruby/src/ruby/parse.y,v retrieving revision 1.378 diff -U2 -p -r1.378 parse.y --- parse.y 1 May 2005 00:15:25 -0000 1.378 +++ parse.y 1 May 2005 00:59:20 -0000 @@ -4445,4 +4445,5 @@ yycompile(parser, f, line) NODE *node = 0; struct RVarmap *vp, *vars = ruby_dyna_vars; + const char *kcode_save; if (!compile_for_eval && rb_safe_level() == 0 && @@ -4468,4 +4469,5 @@ yycompile(parser, f, line) } + kcode_save = rb_get_kcode(); ruby_current_node = 0; ruby_sourcefile = rb_source_filename(f); @@ -4474,4 +4476,5 @@ yycompile(parser, f, line) ruby_debug_lines = 0; compile_for_eval = 0; + rb_set_kcode(kcode_save); vp = ruby_dyna_vars; @@ -5404,14 +5407,11 @@ parser_yylex(parser) case '#': /* it's a comment */ - while ((c = nextc()) != '\n') { - if (c == -1) { -#ifdef RIPPER - ripper_dispatch_scan_event(parser, tCOMMENT); -#endif - return 0; - } + if (lex_p < lex_pend) { + ruby_modeset(lex_p, lex_pend - lex_p); + lex_p = lex_pend; } #ifdef RIPPER ripper_dispatch_scan_event(parser, tCOMMENT); + if (lex_p[-1] != '\n') return 0; fallthru = Qtrue; #endif Index: ruby.c =================================================================== RCS file: /cvs/ruby/src/ruby/ruby.c,v retrieving revision 1.100 diff -U2 -p -r1.100 ruby.c --- ruby.c 1 May 2005 00:13:34 -0000 1.100 +++ ruby.c 1 May 2005 00:59:20 -0000 @@ -401,4 +401,127 @@ require_libraries() } +/* emacsen -*- hack */ +typedef void (*rb_modeset_setter_t) _((const char *val, const char *name)); + +struct modeset { + const char *name; + rb_modeset_setter_t func; +}; + +static const struct modeset modesets[] = { + {"coding", (rb_modeset_setter_t)rb_set_kcode}, +}; + +static const char * +modeset_marker(str, len) + const char *str; + int len; +{ + int i = 2; + + while (i < len) { + switch (str[i]) { + case '-': + if (str[i-1] == '*' && str[i-2] == '-') { + return str + i + 1; + } + i += 2; + break; + case '*': + if (i + 1 >= len) return 0; + if (str[i+1] != '-') { + i += 4; + } + else if (str[i-1] != '-') { + i += 2; + } + else { + return str + i + 2; + } + break; + default: + i += 3; + break; + } + } + return 0; +} + +void +ruby_modeset(str, len) + const char *str; + int len; +{ + VALUE name = 0, val = 0; + const char *beg, *end, *vbeg, *vend; +#define str_copy(_s, _p, _n) ((_s) \ + ? (rb_str_resize((_s), (_n)), \ + MEMCPY(RSTRING(_s)->ptr, (_p), char, (_n)), (_s)) \ + : ((_s) = rb_str_new((_p), (_n)))) + + if (!(beg = modeset_marker(str, len))) return; + if (!(end = modeset_marker(beg, str + len - beg))) return; + str = beg; + len = end - beg - 3; + + /* %r"([^\\s\'\":;]+)\\s*:\\s*(\"(?:\\\\.|[^\"])*\"|[^\"\\s;]+)[\\s;]*" */ + while (len > 0) { + const struct modeset *p = modesets; + int n = 0; + + for (; len > 0 && *str; str++, --len) { + switch (*str) { + case '\'': case '"': case ':': case ';': + continue; + } + if (!ISSPACE(*str)) break; + } + for (beg = str; len > 0; str++, --len) { + switch (*str) { + case '\'': case '"': case ':': case ';': + break; + default: + if (ISSPACE(*str)) break; + continue; + } + break; + } + for (end = str; len > 0 && ISSPACE(*str); str++, --len); + if (!len) break; + if (*str != ':') continue; + + do str++; while (--len > 0 && ISSPACE(*str)); + if (!len) break; + if (*str == '"') { + for (vbeg = ++str; --len > 0 && *str != '"'; str++) { + if (*str == '\\') { + --len; + ++str; + } + } + vend = str; + if (len) { + --len; + ++str; + } + } + else { + for (vbeg = str; len > 0 && *str != '"' && !ISSPACE(*str); --len, str++); + vend = str; + } + while (len > 0 && (*str == ';' || ISSPACE(*str))) --len, str++; + + str_copy(name, beg, end - beg); + rb_funcall(name, rb_intern("downcase!"), 0); + do { + if (strncmp(p->name, RSTRING(name)->ptr, n) == 0) { + str_copy(val, vbeg, vend - vbeg); + (*p->func)(RSTRING(val)->ptr, RSTRING(name)->ptr); + break; + } + } while (++p < modesets + sizeof(modesets) / sizeof(*p)); + } +} + static void process_sflag() @@ -967,4 +1090,7 @@ load_file(fname, script) } } + else if (RSTRING(line)->len > 7) { + ruby_modeset(RSTRING(line)->ptr, RSTRING(line)->len); + } } else if (!NIL_P(c)) { -- Nobu Nakada