From 7894831e9078211df0b460c4d3dd1bc51ca46804 Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Thu, 17 May 2018 10:45:49 +0100 Subject: [PATCH] admin.scala: Start on understanding the administration protocol. --- Makefile | 2 ++ admin.scala | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 admin.scala diff --git a/Makefile b/Makefile index 873380a..cd8e4a4 100644 --- a/Makefile +++ b/Makefile @@ -53,6 +53,8 @@ TARGETS += jni.stamp TARGETS += sock.stamp sock.stamp: jni.stamp +TARGETS += admin.stamp + TARGETS += main.stamp main.stamp: jni.stamp sock.stamp diff --git a/admin.scala b/admin.scala new file mode 100644 index 0000000..85978fe --- /dev/null +++ b/admin.scala @@ -0,0 +1,72 @@ +package uk.org.distorted.tripe; + +import scala.collection.mutable.ArrayBuffer; + +object Admin { + val RX_ORDINARY = "^[^\\\\'\"\\s]+$".r; + val RX_WEIRD = "[\\\\'\"]".r; + + def quote(v: Seq[String]) = { + val b = new StringBuilder; + var sep = false; + for (s <- v) { + if (!sep) sep = true; + else b.append(' '); + s match { + case RX_ORDINARY() => b.append(s); + case _ => + b.append('"'); + b.append(RX_WEIRD.replaceAllIn(s, "\\\\$0")); + b.append('"'); + } + } + b.mkString + } + + class InvalidQuotingException(msg: String) extends Exception(msg); + + def split(s: String): Array[String] = { + val ab = new ArrayBuffer[String](); + val sb = new StringBuilder; + + object State extends Enumeration { + val BETWEEN, WORD, SQUOTE, DQUOTE = Value; + } + import State.{Value => _, _}; + + val n = s.length; + + def scan(pos: Int, st: State.Value, bs: Boolean) + { + if (pos >= n) { + if (bs) + throw new InvalidQuotingException("trailing `\\'"); + else if (st == SQUOTE || st == DQUOTE) + throw new InvalidQuotingException("unmatched quote"); + if (st != BETWEEN) ab += sb.mkString; + } else (st, bs, s(pos)) match { + case (BETWEEN, false, '\\') => scan(pos + 1, WORD, true); + case (_, false, '\\') => scan(pos + 1, st, true); + case (SQUOTE, false, ''') | (DQUOTE, false, '"') => + scan(pos + 1, WORD, false); + case (BETWEEN | WORD, false, ''') => scan(pos + 1, SQUOTE, false); + case (BETWEEN | WORD, false, '"') => scan(pos + 1, DQUOTE, false); + case (BETWEEN, false, ch) if ch.isWhitespace => + scan(pos + 1, st, false); + case (WORD, false, ch) if ch.isWhitespace => + ab += sb.mkString; sb.clear(); + scan(pos + 1, BETWEEN, false); + case (BETWEEN, _, ch) => sb.append(ch); scan(pos + 1, WORD, false); + case (_, _, ch) => sb.append(ch); scan(pos + 1, st, false); + } + } + scan(0, BETWEEN, false); + ab.toArray + } + + def main(args: Array[String]) + { + if (args.length != 1) println(quote(args)); + else for (s <- split(args(0))) println(s); + } +} -- 2.11.0