int here_document(int term, int indent) { int c; string line = String.Empty; RNode list = null; int linesave = thread.line; newtok(); switch (term) { case '\'': goto case '`'; case '"': goto case '`'; case '`': while ((c = nextc()) != term) { tokadd(c); } if (term == '\'') term = '\0'; break; default: c = term; term = '"'; if (!is_identchar(c)) { ruby.warn("use of bare << to mean <<\"\" is deprecated"); break; } while (is_identchar(c)) { tokadd(c); c = nextc(); } pushback(c); break; } string lastline_save = lastline; int offset_save = pcur - pbeg; string eos = string.Copy(tok()); int len = eos.Length; string str = String.Empty; for (;;) { lastline = line = getline(); if (line == null) { thread.line = linesave; thread.CompileError("can't find string \"" + eos + "\" anywhere before EOF"); return 0; } thread.line++; string p = line; if (indent > 0) { while (p.Length > 0 && (p[0] == ' ' || p[0] == '\t')) { p = p.Substring(1); } } if (String.Compare(eos, 0, p, 0, len) == 0) { if (p[len] == '\n' || p[len] == '\r') break; if (len == line.Length) break; } pbeg = pcur = 0; pend = pcur + line.Length; retry: switch (parse_string(term, '\n', '\n')) { case Token.tSTRING: // fall down to the next case case Token.tXSTRING: { yylval = (string)yylval + "\n"; } if (list == null) { str += (string)yylval; } else { RNode.list_append(thread, list, new RNStr(thread, ruby, (string)yylval)); } break; case Token.tDSTRING: if (list == null) list = new RNDStr(thread, ruby, str); goto case Token.tDXSTRING; case Token.tDXSTRING: if (list == null) list = new RNDXStr(thread, ruby, str); RNode.list_append(thread, (RNode)yylval, new RNStr(thread, ruby, "\n")); RNStr val = new RNStr((RNStr)yylval); yylval = new RNArray(thread, val); ((RNode)yylval).next = ((RNode)yylval).head.next; RNode.list_concat(list, (RNode)yylval); break; case 0: thread.line = linesave; thread.CompileError("can't find string \"" + eos + "\" anywhere before EOF"); return 0; } if (pcur != pend) { goto retry; } } lastline = lastline_save; pbeg = 0; pend = lastline.Length; pcur = offset_save; lex_state = EXPR.END; heredoc_end = thread.line; thread.line = linesave; if (list != null) { list.SetLine(linesave+1); yylval = list; } switch (term) { case '\0': goto case '"'; case '\'': goto case '"'; case '"': if (list != null) return Token.tDSTRING; yylval = str; return Token.tSTRING; case '`': if (list != null) return Token.tDXSTRING; yylval = str; return Token.tXSTRING; } return 0; }
int parse_quotedwords(int term, int paren) { RNode qwords = null; int strstart = thread.line; int c; int nest = 0; newtok(); for (c = nextc(); Char.IsWhiteSpace((char)c); c = nextc()) ; /* skip preceding spaces */ pushback(c); while ((c = nextc()) != term || nest > 0) { if (c == -1) { thread.line = strstart; thread.CompileError("unterminated string meets end of file"); return 0; } /* if (ismbchar(c)) { int i, len = mbclen(c)-1; for (i = 0; i < len; i++) { tokadd(c); c = nextc(); } } */ else if (c == '\\') { c = nextc(); switch (c) { case '\n': continue; case '\\': c = '\\'; break; default: if (c == term) { tokadd(c); continue; } if (!Char.IsWhiteSpace((char)c)) tokadd('\\'); break; } } else if (Char.IsWhiteSpace((char)c)) { RNode str = new RNStr(thread, ruby, tok()); newtok(); if (qwords == null) qwords = new RNArray(thread, str); else RNode.list_append(thread, qwords, str); for (c = nextc(); Char.IsWhiteSpace((char)c); c = nextc()) ; /* skip continuous spaces */ pushback(c); continue; } if (paren != 0) { if (c == paren) nest++; if (c == term && nest-- == 0) break; } tokadd(c); } if (toklen() > 0) { RNode str = new RNStr(thread, ruby, tok()); if (qwords == null) qwords = new RNArray(thread, str); else RNode.list_append(thread, qwords, str); } if (qwords == null) qwords = new RNZArray(thread); yylval = qwords; lex_state = EXPR.END; return Token.tDSTRING; }