heredoc << support
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1736058 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Parser.java b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Parser.java
index 862bef6..f6fb81a 100644
--- a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Parser.java
+++ b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Parser.java
@@ -308,6 +308,7 @@
private static final Pattern redirNoArg = Pattern.compile("[0-9]?>&[0-9-]|[0-9-]?<&[0-9-]");
private static final Pattern redirArg = Pattern.compile("[0-9&]?>|[0-9]?>>|[0-9]?<|[0-9]?<>|<<<");
+ private static final Pattern redirHereDoc = Pattern.compile("<<-?");
public Statement statement()
{
@@ -366,6 +367,11 @@
redirs.add(t);
needRedirArg = true;
}
+ else if (redirHereDoc.matcher(t).matches())
+ {
+ redirs.add(t);
+ redirs.add(tz.readHereDoc(t.charAt(t.length() - 1) == '-'));
+ }
else
{
tokens.add(t);
diff --git a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Pipe.java b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Pipe.java
index fc9bc67..91b459d 100644
--- a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Pipe.java
+++ b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Pipe.java
@@ -338,6 +338,37 @@
setStream(ch, fd, READ + (output ? WRITE : 0));
}
}
+ else if ((m = Pattern.compile("<<-?").matcher(t)).matches())
+ {
+ Token hereDoc = tokens.get(++i);
+ boolean stripLeadingTabs = t.charAt(t.length() - 1) == '-';
+ InputStream doc = new InputStream()
+ {
+ final byte[] bytes = hereDoc.toString().getBytes();
+ int index = 0;
+ boolean nl = true;
+ @Override
+ public int read() throws IOException
+ {
+ if (nl && stripLeadingTabs)
+ {
+ while (index < bytes.length && bytes[index] == '\t')
+ {
+ index++;
+ }
+ }
+ if (index < bytes.length)
+ {
+ int ch = bytes[index++];
+ nl = ch == '\n';
+ return ch;
+ }
+ return -1;
+ }
+ };
+ Channel ch = Channels.newChannel(doc);
+ setStream(ch, 0, READ);
+ }
else if (Token.eq("<<<", t))
{
Token word = tokens.get(++i);
diff --git a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Tokenizer.java b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Tokenizer.java
index 549cb5c..e9cec78 100644
--- a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Tokenizer.java
+++ b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Tokenizer.java
@@ -23,7 +23,7 @@
public class Tokenizer extends BaseTokenizer
{
- private final Pattern redir = Pattern.compile("[0-9&]?>|[0-9]?>>|[0-9]?>&|[0-9]?<|[0-9]?<>|<<<");
+ private final Pattern redir = Pattern.compile("[0-9&]?>|[0-9]?>>|[0-9]?>&|[0-9]?<|[0-9]?<>|<<<|<<\\-?");
protected boolean inArray;
protected int word = 0;
@@ -119,6 +119,17 @@
}
word = 0;
return token(start);
+ case '-':
+ t = text.subSequence(start, index);
+ if (redir.matcher(t).matches())
+ {
+ getch();
+ return token(start);
+ }
+ else {
+ getch();
+ break;
+ }
case '&':
// beginning of token
if (start == index - 1) {
@@ -211,4 +222,58 @@
this.pushed = token;
}
+ public Token readHereDoc(boolean ignoreLeadingTabs)
+ {
+ final short sLine = line;
+ final short sCol = column;
+ int start;
+ int nlIndex;
+ boolean nl;
+ // Find word
+ skipSpace();
+ start = index - 1;
+ while (ch != '\n' && ch != EOT) {
+ getch();
+ }
+ if (ch == EOT) {
+ throw new EOFError(sLine, sCol, "expected here-doc start", "heredoc", "foo");
+ }
+ Token token = text.subSequence(start, index - 1);
+ getch();
+ start = index - 1;
+ nlIndex = start;
+ nl = true;
+ // Get heredoc
+ while (true)
+ {
+ if (nl)
+ {
+ if (ignoreLeadingTabs && ch == '\t')
+ {
+ nlIndex++;
+ }
+ else
+ {
+ nl = false;
+ }
+ }
+ if (ch == '\n' || ch == EOT)
+ {
+ Token s = text.subSequence(nlIndex, index - 1);
+ if (Token.eq(s, token))
+ {
+ Token hd = text.subSequence(start, s.start());
+ getch();
+ return hd;
+ }
+ nlIndex = index;
+ nl = true;
+ }
+ if (ch == EOT)
+ {
+ throw new EOFError(sLine, sCol, "unexpected eof found in here-doc", "heredoc", token.toString());
+ }
+ getch();
+ }
+ }
}
diff --git a/gogo/runtime/src/test/java/org/apache/felix/gogo/runtime/TestParser4.java b/gogo/runtime/src/test/java/org/apache/felix/gogo/runtime/TestParser4.java
index ec69734..5bcb6a3 100644
--- a/gogo/runtime/src/test/java/org/apache/felix/gogo/runtime/TestParser4.java
+++ b/gogo/runtime/src/test/java/org/apache/felix/gogo/runtime/TestParser4.java
@@ -62,6 +62,9 @@
Files.deleteIfExists(path.resolve("foo"));
assertEquals("hello\n", c.execute("echo hello>foo | tac"));
assertEquals("hello\n", new String(Files.readAllBytes(path.resolve("foo"))));
+
+ Files.deleteIfExists(path.resolve("foo2"));
+ assertEquals("hello\n", c.execute("echo hello>\\\nfoo2 | tac"));
}
@Test
@@ -152,6 +155,18 @@
assertEquals("ar1 ar2\n", c.execute("cat <<<$c | tac"));
}
+ @Test
+ public void testHereDoc() throws Exception
+ {
+ Context c = new Context();
+ c.addCommand("echo", this);
+ c.addCommand("tac", this);
+ c.addCommand("cat", this);
+
+ assertEquals("bar\nbaz\n", c.execute("cat <<foo\nbar\nbaz\nfoo\n| tac"));
+ assertEquals("bar\nbaz\n", c.execute("cat <<-foo\n\tbar\n\tbaz\n\tfoo\n| tac"));
+ }
+
public void echo(String msg)
{
System.out.println(msg);