diff options
author | Benoit Foucher <benoit@zeroc.com> | 2006-01-31 09:59:27 +0000 |
---|---|---|
committer | Benoit Foucher <benoit@zeroc.com> | 2006-01-31 09:59:27 +0000 |
commit | 92d1dd75cf0c8e515e694b2e254079f5b67119b6 (patch) | |
tree | 7fcf2099e93edd91e1c02af628c88a762fbcae08 /java/src/IceUtil/Options.java | |
parent | Renamed Thread::done() to Thread::_done(), to make it clearer that this (diff) | |
download | ice-92d1dd75cf0c8e515e694b2e254079f5b67119b6.tar.bz2 ice-92d1dd75cf0c8e515e694b2e254079f5b67119b6.tar.xz ice-92d1dd75cf0c8e515e694b2e254079f5b67119b6.zip |
Added ANSI quote support.
Diffstat (limited to 'java/src/IceUtil/Options.java')
-rw-r--r-- | java/src/IceUtil/Options.java | 228 |
1 files changed, 225 insertions, 3 deletions
diff --git a/java/src/IceUtil/Options.java b/java/src/IceUtil/Options.java index 39bb305db1a..7db0c20ed8d 100644 --- a/java/src/IceUtil/Options.java +++ b/java/src/IceUtil/Options.java @@ -27,6 +27,7 @@ public final class Options final int NormalState = 1; final int DoubleQuoteState = 2; final int SingleQuoteState = 3; + final int ANSIQuoteState = 4; line = line.trim(); @@ -48,12 +49,35 @@ public final class Options { // // Ignore a backslash at the end of the string, - // and strip backslash-newline pairs. Anything - // else following a backslash is taken literally. + // and strip backslash-newline pairs. If a + // backslash is followed by a space, single quote, + // double quote, or dollar sign, we drop the backslash + // and write the space, single quote, double quote, + // or dollar sign. This is necessary to allow quotes + // to be escaped. Dropping the backslash preceding a + // space deviates from bash quoting rules, but is + // necessary so we don't drop backslashes from Windows + // path names.) // if(i < line.length() - 1 && line.charAt(++i) != '\n') { - arg.append(line.charAt(i)); + switch(line.charAt(i)) + { + case ' ': + case '$': + case '\\': + case '"': + { + arg.append(line.charAt(i)); + break; + } + default: + { + arg.append('\\'); + arg.append(line.charAt(i)); + break; + } + } } break; } @@ -67,6 +91,19 @@ public final class Options state = DoubleQuoteState; break; } + case '$': + { + if(i < line.length() - 1 && line.charAt(i + 1) == '\'') + { + state = ANSIQuoteState; // Bash uses $'<text>' to allow ANSI escape sequences within <text>. + ++i; + } + else + { + arg.append('$'); + } + break; + } default: { if(IFS.indexOf(line.charAt(i)) != -1) @@ -138,6 +175,191 @@ public final class Options } break; } + case ANSIQuoteState: + { + switch(c) + { + case '\\': + { + if(i == line.length() - 1) + { + break; + } + switch(c = line.charAt(++i)) + { + // + // Single-letter escape sequences. + // + case 'a': + { + arg.append('\007'); + break; + } + case 'b': + { + arg.append('\b'); + break; + } + case 'f': + { + arg.append('\f'); + break; + } + case 'n': + { + arg.append('\n'); + break; + } + case 'r': + { + arg.append('\r'); + break; + } + case 't': + { + arg.append('\t'); + break; + } + case 'v': + { + arg.append('\013'); + break; + } + case '\\': + { + arg.append('\\'); + break; + } + case '\'': + { + arg.append('\''); + break; + } + case 'e': // Not ANSI-C, but used by bash. + { + arg.append('\033'); + break; + } + + // + // Process up to three octal digits. + // + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + { + final String octalDigits = "01234567"; + short us = 0; + int j; + for(j = i; + j < i + 3 && j < line.length() && octalDigits.indexOf(c = line.charAt(j)) != -1; + ++j) + { + us = (short)(us * 8 + c - '0'); + } + i = j - 1; + arg.append((char)us); + break; + } + + // + // Process up to two hex digits. + // + case 'x': + { + final String hexDigits = "0123456789abcdefABCDEF"; + if(i < line.length() - 1 && hexDigits.indexOf(line.charAt(i + 1)) == -1) + { + arg.append('\\'); + arg.append('x'); + break; + } + + short s = 0; + int j; + for(j = i + 1; + j < i + 3 && j < line.length() && hexDigits.indexOf(c = line.charAt(j)) != -1; + ++j) + { + s *= 16; + if(Character.isDigit(c)) + { + s += (short)(c - '0'); + } + else if(Character.isLowerCase(c)) + { + s += (short)(c - 'a' + 10); + } + else + { + s += (short)(c - 'A' + 10); + } + } + i = j - 1; + arg.append((char)s); + break; + } + + // + // Process control-chars. + // + case 'c': + { + c = line.charAt(++i); + if((Character.toUpperCase(c) >= 'A' && Character.toUpperCase(c) <= 'Z') || + c == '@' || + (c >= '[' && c <= '_')) + { + arg.append((char)(Character.toUpperCase(c) - '@')); + } + else + { + // + // Bash does not define what should happen if a \c + // is not followed by a recognized control character. + // We simply treat this case like other unrecognized + // escape sequences, that is, we preserve the escape + // sequence unchanged. + // + arg.append('\\'); + arg.append('c'); + arg.append(c); + } + break; + } + + // + // If inside an ANSI-quoted string, a backslash isn't followed by + // one of the recognized characters, both the backslash and the + // character are preserved. + // + default: + { + arg.append('\\'); + arg.append(c); + break; + } + } + break; + } + case '\'': // End of ANSI-quote mode. + { + state = NormalState; + break; + } + default: + { + arg.append(c); // Everything else is taken literally. + break; + } + } + break; + } default: assert(false); break; |