map =
- new HashMap<>((int)(649 / 0.75f + 1.0f));
+ new HashMap<>((int)(NUM_ENTITIES / 0.75f + 1.0f));
/**
* Creates a UnicodeBlock with the given identifier name.
diff -r a659ccd1888d -r ddbd9744a3d5 src/java.base/share/classes/java/lang/Object.java
--- a/src/java.base/share/classes/java/lang/Object.java Tue Dec 11 11:45:43 2018 +0530
+++ b/src/java.base/share/classes/java/lang/Object.java Wed Dec 12 15:04:47 2018 +0530
@@ -94,12 +94,10 @@
* programmer should be aware that producing distinct integer results
* for unequal objects may improve the performance of hash tables.
*
- *
- * As much as is reasonably practical, the hashCode method defined
- * by class {@code Object} does return distinct integers for
- * distinct objects. (The hashCode may or may not be implemented
- * as some function of an object's memory address at some point
- * in time.)
+ *
+ * @implSpec
+ * As far as is reasonably practical, the {@code hashCode} method defined
+ * by class {@code Object} returns distinct integers for distinct objects.
*
* @return a hash code value for this object.
* @see java.lang.Object#equals(java.lang.Object)
diff -r a659ccd1888d -r ddbd9744a3d5 src/java.base/share/classes/java/net/URI.java
--- a/src/java.base/share/classes/java/net/URI.java Tue Dec 11 11:45:43 2018 +0530
+++ b/src/java.base/share/classes/java/net/URI.java Wed Dec 12 15:04:47 2018 +0530
@@ -25,6 +25,7 @@
package java.net;
+import java.io.File;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
@@ -36,6 +37,7 @@
import java.nio.charset.CoderResult;
import java.nio.charset.CodingErrorAction;
import java.nio.charset.CharacterCodingException;
+import java.nio.file.Path;
import java.text.Normalizer;
import jdk.internal.access.JavaNetUriAccess;
import jdk.internal.access.SharedSecrets;
@@ -458,6 +460,27 @@
* resolution as well as the network I/O operations of looking up the host and
* opening a connection to the specified resource.
*
+ * @apiNote
+ *
+ * Applications working with file paths and file URIs should take great
+ * care to use the appropriate methods to convert between the two.
+ * The {@link Path#of(URI)} factory method and the {@link File#File(URI)}
+ * constructor can be used to create {@link Path} or {@link File}
+ * objects from a file URI. {@link Path#toUri()} and {@link File#toURI()}
+ * can be used to create a {@link URI} from a file path.
+ * Applications should never try to {@linkplain
+ * #URI(String, String, String, int, String, String, String)
+ * construct}, {@linkplain #URI(String) parse}, or
+ * {@linkplain #resolve(String) resolve} a {@code URI}
+ * from the direct string representation of a {@code File} or {@code Path}
+ * instance.
+ *
+ * Some components of a URL or URI, such as userinfo, may
+ * be abused to construct misleading URLs or URIs. Applications
+ * that deal with URLs or URIs should take into account
+ * the recommendations advised in RFC3986,
+ * Section 7, Security Considerations.
*
* @author Mark Reinhold
* @since 1.4
diff -r a659ccd1888d -r ddbd9744a3d5 src/java.base/share/classes/java/net/URL.java
--- a/src/java.base/share/classes/java/net/URL.java Tue Dec 11 11:45:43 2018 +0530
+++ b/src/java.base/share/classes/java/net/URL.java Wed Dec 12 15:04:47 2018 +0530
@@ -25,9 +25,11 @@
package java.net;
+import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.spi.URLStreamHandlerProvider;
+import java.nio.file.Path;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Hashtable;
@@ -145,6 +147,27 @@
* used, but only for HTML form encoding, which is not the same
* as the encoding scheme defined in RFC2396.
*
+ * @apiNote
+ *
+ * Applications working with file paths and file URIs should take great
+ * care to use the appropriate methods to convert between the two.
+ * The {@link Path#of(URI)} factory method and the {@link File#File(URI)}
+ * constructor can be used to create {@link Path} or {@link File}
+ * objects from a file URI. {@link Path#toUri()} and {@link File#toURI()}
+ * can be used to create a {@link URI} from a file path, which can be
+ * converted to URL using {@link URI#toURL()}.
+ * Applications should never try to {@linkplain #URL(String, String, String)
+ * construct} or {@linkplain #URL(String) parse} a {@code URL}
+ * from the direct string representation of a {@code File} or {@code Path}
+ * instance.
+ *
+ * Some components of a URL or URI, such as userinfo, may
+ * be abused to construct misleading URLs or URIs. Applications
+ * that deal with URLs or URIs should take into account
+ * the recommendations advised in RFC3986,
+ * Section 7, Security Considerations.
+ *
* @author James Gosling
* @since 1.0
*/
diff -r a659ccd1888d -r ddbd9744a3d5 src/java.base/share/classes/java/util/SplittableRandom.java
--- a/src/java.base/share/classes/java/util/SplittableRandom.java Tue Dec 11 11:45:43 2018 +0530
+++ b/src/java.base/share/classes/java/util/SplittableRandom.java Wed Dec 12 15:04:47 2018 +0530
@@ -80,7 +80,7 @@
* in security-sensitive applications. Additionally,
* default-constructed instances do not use a cryptographically random
* seed unless the {@linkplain System#getProperty system property}
- * {@code java.util.secureRandomSeed} is set to {@code true}.
+ * {@systemProperty java.util.secureRandomSeed} is set to {@code true}.
*
* @author Guy Steele
* @author Doug Lea
diff -r a659ccd1888d -r ddbd9744a3d5 src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java
--- a/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java Tue Dec 11 11:45:43 2018 +0530
+++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java Wed Dec 12 15:04:47 2018 +0530
@@ -2334,17 +2334,15 @@
Node[] tab, nt; int n, sc;
while (s >= (long)(sc = sizeCtl) && (tab = table) != null &&
(n = tab.length) < MAXIMUM_CAPACITY) {
- int rs = resizeStamp(n);
+ int rs = resizeStamp(n) << RESIZE_STAMP_SHIFT;
if (sc < 0) {
- if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||
- sc == rs + MAX_RESIZERS || (nt = nextTable) == null ||
- transferIndex <= 0)
+ if (sc == rs + MAX_RESIZERS || sc == rs + 1 ||
+ (nt = nextTable) == null || transferIndex <= 0)
break;
if (U.compareAndSetInt(this, SIZECTL, sc, sc + 1))
transfer(tab, nt);
}
- else if (U.compareAndSetInt(this, SIZECTL, sc,
- (rs << RESIZE_STAMP_SHIFT) + 2))
+ else if (U.compareAndSetInt(this, SIZECTL, sc, rs + 2))
transfer(tab, null);
s = sumCount();
}
@@ -2358,11 +2356,11 @@
Node[] nextTab; int sc;
if (tab != null && (f instanceof ForwardingNode) &&
(nextTab = ((ForwardingNode)f).nextTable) != null) {
- int rs = resizeStamp(tab.length);
+ int rs = resizeStamp(tab.length) << RESIZE_STAMP_SHIFT;
while (nextTab == nextTable && table == tab &&
(sc = sizeCtl) < 0) {
- if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||
- sc == rs + MAX_RESIZERS || transferIndex <= 0)
+ if (sc == rs + MAX_RESIZERS || sc == rs + 1 ||
+ transferIndex <= 0)
break;
if (U.compareAndSetInt(this, SIZECTL, sc, sc + 1)) {
transfer(tab, nextTab);
diff -r a659ccd1888d -r ddbd9744a3d5 src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java
--- a/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java Tue Dec 11 11:45:43 2018 +0530
+++ b/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java Wed Dec 12 15:04:47 2018 +0530
@@ -136,17 +136,17 @@
* The parameters used to construct the common pool may be controlled by
* setting the following {@linkplain System#getProperty system properties}:
*
- * - {@code java.util.concurrent.ForkJoinPool.common.parallelism}
+ *
- {@systemProperty java.util.concurrent.ForkJoinPool.common.parallelism}
* - the parallelism level, a non-negative integer
- *
- {@code java.util.concurrent.ForkJoinPool.common.threadFactory}
+ *
- {@systemProperty java.util.concurrent.ForkJoinPool.common.threadFactory}
* - the class name of a {@link ForkJoinWorkerThreadFactory}.
* The {@linkplain ClassLoader#getSystemClassLoader() system class loader}
* is used to load this class.
- *
- {@code java.util.concurrent.ForkJoinPool.common.exceptionHandler}
+ *
- {@systemProperty java.util.concurrent.ForkJoinPool.common.exceptionHandler}
* - the class name of a {@link UncaughtExceptionHandler}.
* The {@linkplain ClassLoader#getSystemClassLoader() system class loader}
* is used to load this class.
- *
- {@code java.util.concurrent.ForkJoinPool.common.maximumSpares}
+ *
- {@systemProperty java.util.concurrent.ForkJoinPool.common.maximumSpares}
* - the maximum number of allowed extra threads to maintain target
* parallelism (default 256).
*
@@ -445,8 +445,7 @@
* if to its current value). This would be extremely costly. So
* we relax it in several ways: (1) Producers only signal when
* their queue is possibly empty at some point during a push
- * operation (which requires conservatively checking size zero or
- * one to cover races). (2) Other workers propagate this signal
+ * operation. (2) Other workers propagate this signal
* when they find tasks in a queue with size greater than one. (3)
* Workers only enqueue after scanning (see below) and not finding
* any tasks. (4) Rather than CASing ctl to its current value in
@@ -762,10 +761,8 @@
/**
* The maximum number of top-level polls per worker before
- * checking other queues, expressed as a bit shift to, in effect,
- * multiply by pool size, and then use as random value mask, so
- * average bound is about poolSize*(1< task) {
ForkJoinTask>[] a;
- int s = top, d, cap, m;
+ int s = top, d = s - base, cap, m;
ForkJoinPool p = pool;
if ((a = array) != null && (cap = a.length) > 0) {
QA.setRelease(a, (m = cap - 1) & s, task);
top = s + 1;
- if (((d = s - (int)BASE.getAcquire(this)) & ~1) == 0 &&
- p != null) { // size 0 or 1
- VarHandle.fullFence();
- p.signalWork();
+ if (d == m)
+ growArray(false);
+ else if (QA.getAcquire(a, m & (s - 1)) == null && p != null) {
+ VarHandle.fullFence(); // was empty
+ p.signalWork(null);
}
- else if (d == m)
- growArray(false);
}
}
@@ -863,16 +859,16 @@
final boolean lockedPush(ForkJoinTask> task) {
ForkJoinTask>[] a;
boolean signal = false;
- int s = top, b = base, cap, d;
+ int s = top, d = s - base, cap, m;
if ((a = array) != null && (cap = a.length) > 0) {
- a[(cap - 1) & s] = task;
+ a[(m = (cap - 1)) & s] = task;
top = s + 1;
- if (b - s + cap - 1 == 0)
+ if (d == m)
growArray(true);
else {
phase = 0; // full volatile unlock
- if (((s - base) & ~1) == 0) // size 0 or 1
- signal = true;
+ if (a[m & (s - 1)] == null)
+ signal = true; // was empty
}
}
return signal;
@@ -1014,25 +1010,30 @@
* queue, up to bound n (to avoid infinite unfairness).
*/
final void topLevelExec(ForkJoinTask> t, WorkQueue q, int n) {
- if (t != null && q != null) { // hoist checks
- int nstolen = 1;
- for (;;) {
+ int nstolen = 1;
+ for (int j = 0;;) {
+ if (t != null)
t.doExec();
- if (n-- < 0)
+ if (j++ <= n)
+ t = nextLocalTask();
+ else {
+ j = 0;
+ t = null;
+ }
+ if (t == null) {
+ if (q != null && (t = q.poll()) != null) {
+ ++nstolen;
+ j = 0;
+ }
+ else if (j != 0)
break;
- else if ((t = nextLocalTask()) == null) {
- if ((t = q.poll()) == null)
- break;
- else
- ++nstolen;
- }
}
- ForkJoinWorkerThread thread = owner;
- nsteals += nstolen;
- source = 0;
- if (thread != null)
- thread.afterTopLevelExec();
}
+ ForkJoinWorkerThread thread = owner;
+ nsteals += nstolen;
+ source = 0;
+ if (thread != null)
+ thread.afterTopLevelExec();
}
/**
@@ -1455,7 +1456,7 @@
if (!tryTerminate(false, false) && // possibly replace worker
w != null && w.array != null) // avoid repeated failures
- signalWork();
+ signalWork(null);
if (ex == null) // help clean on way out
ForkJoinTask.helpExpungeStaleExceptions();
@@ -1465,8 +1466,9 @@
/**
* Tries to create or release a worker if too few are running.
+ * @param q if non-null recheck if empty on CAS failure
*/
- final void signalWork() {
+ final void signalWork(WorkQueue q) {
for (;;) {
long c; int sp; WorkQueue[] ws; int i; WorkQueue v;
if ((c = ctl) >= 0L) // enough workers
@@ -1493,6 +1495,8 @@
LockSupport.unpark(vt);
break;
}
+ else if (q != null && q.isEmpty()) // no need to retry
+ break;
}
}
}
@@ -1613,19 +1617,24 @@
else if (rc <= 0 && (md & SHUTDOWN) != 0 &&
tryTerminate(false, false))
break; // quiescent shutdown
- else if (rc <= 0 && pred != 0 && phase == (int)c) {
- long nc = (UC_MASK & (c - TC_UNIT)) | (SP_MASK & pred);
- long d = keepAlive + System.currentTimeMillis();
- LockSupport.parkUntil(this, d);
- if (ctl == c && // drop on timeout if all idle
- d - System.currentTimeMillis() <= TIMEOUT_SLOP &&
- CTL.compareAndSet(this, c, nc)) {
- w.phase = QUIET;
- break;
+ else if (w.phase < 0) {
+ if (rc <= 0 && pred != 0 && phase == (int)c) {
+ long nc = (UC_MASK & (c - TC_UNIT)) | (SP_MASK & pred);
+ long d = keepAlive + System.currentTimeMillis();
+ LockSupport.parkUntil(this, d);
+ if (ctl == c && // drop on timeout if all idle
+ d - System.currentTimeMillis() <= TIMEOUT_SLOP &&
+ CTL.compareAndSet(this, c, nc)) {
+ w.phase = QUIET;
+ break;
+ }
+ }
+ else {
+ LockSupport.park(this);
+ if (w.phase < 0) // one spurious wakeup check
+ LockSupport.park(this);
}
}
- else if (w.phase < 0)
- LockSupport.park(this); // OK if spuriously woken
w.source = 0; // disable signal
}
}
@@ -1641,8 +1650,8 @@
WorkQueue[] ws; int n;
if ((ws = workQueues) != null && (n = ws.length) > 0 && w != null) {
for (int m = n - 1, j = r & m;;) {
- WorkQueue q; int b;
- if ((q = ws[j]) != null && q.top != (b = q.base)) {
+ WorkQueue q; int b, s;
+ if ((q = ws[j]) != null && (s = q.top) != (b = q.base)) {
int qid = q.id;
ForkJoinTask>[] a; int cap, k; ForkJoinTask> t;
if ((a = q.array) != null && (cap = a.length) > 0) {
@@ -1651,10 +1660,10 @@
QA.compareAndSet(a, k, t, null)) {
q.base = b;
w.source = qid;
- if (q.top - b > 0)
- signalWork();
+ if (s != b && a[(cap - 1) & b] != null)
+ signalWork(q); // help signal if more tasks
w.topLevelExec(t, q, // random fairness bound
- r & ((n << TOP_BOUND_SHIFT) - 1));
+ (r | (1 << TOP_BOUND_SHIFT)) & SMASK);
}
}
return true;
@@ -1900,7 +1909,7 @@
r = ThreadLocalRandom.advanceProbe(r);
else {
if (q.lockedPush(task))
- signalWork();
+ signalWork(null);
return;
}
}
diff -r a659ccd1888d -r ddbd9744a3d5 src/java.base/share/classes/java/util/concurrent/locks/Lock.java
--- a/src/java.base/share/classes/java/util/concurrent/locks/Lock.java Tue Dec 11 11:45:43 2018 +0530
+++ b/src/java.base/share/classes/java/util/concurrent/locks/Lock.java Wed Dec 12 15:04:47 2018 +0530
@@ -122,7 +122,7 @@
* All {@code Lock} implementations must enforce the same
* memory synchronization semantics as provided by the built-in monitor
* lock, as described in
- *
+ *
* Chapter 17 of
* The Java™ Language Specification:
*
diff -r a659ccd1888d -r ddbd9744a3d5 src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java
--- a/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java Tue Dec 11 11:45:43 2018 +0530
+++ b/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java Wed Dec 12 15:04:47 2018 +0530
@@ -133,7 +133,7 @@
* Memory Synchronization. Methods with the effect of
* successfully locking in any mode have the same memory
* synchronization effects as a Lock action described in
- *
+ *
* Chapter 17 of The Java™ Language Specification.
* Methods successfully unlocking in write mode have the same memory
* synchronization effects as an Unlock action. In optimistic
diff -r a659ccd1888d -r ddbd9744a3d5 src/java.base/share/classes/java/util/concurrent/package-info.java
--- a/src/java.base/share/classes/java/util/concurrent/package-info.java Tue Dec 11 11:45:43 2018 +0530
+++ b/src/java.base/share/classes/java/util/concurrent/package-info.java Wed Dec 12 15:04:47 2018 +0530
@@ -226,7 +226,7 @@
*
*
Memory Consistency Properties
*
- *
+ *
* Chapter 17 of
* The Java™ Language Specification defines the
* happens-before relation on memory operations such as reads and
diff -r a659ccd1888d -r ddbd9744a3d5 src/java.base/share/classes/sun/security/ssl/ClientHandshakeContext.java
--- a/src/java.base/share/classes/sun/security/ssl/ClientHandshakeContext.java Tue Dec 11 11:45:43 2018 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/ClientHandshakeContext.java Wed Dec 12 15:04:47 2018 +0530
@@ -90,6 +90,9 @@
ClientHelloMessage initialClientHelloMsg = null;
+ // PSK identity is selected in first Hello and used again after HRR
+ byte[] pskIdentity;
+
ClientHandshakeContext(SSLContextImpl sslContext,
TransportContext conContext) throws IOException {
super(sslContext, conContext);
diff -r a659ccd1888d -r ddbd9744a3d5 src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java
--- a/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java Tue Dec 11 11:45:43 2018 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java Wed Dec 12 15:04:47 2018 +0530
@@ -656,7 +656,11 @@
return null;
}
SecretKey psk = pskOpt.get();
- Optional pskIdOpt = chc.resumingSession.consumePskIdentity();
+ // The PSK ID can only be used in one connections, but this method
+ // may be called twice in a connection if the server sends HRR.
+ // ID is saved in the context so it can be used in the second call.
+ Optional pskIdOpt = Optional.ofNullable(chc.pskIdentity)
+ .or(chc.resumingSession::consumePskIdentity);
if (!pskIdOpt.isPresent()) {
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
SSLLogger.fine(
@@ -664,7 +668,7 @@
}
return null;
}
- byte[] pskId = pskIdOpt.get();
+ chc.pskIdentity = pskIdOpt.get();
//The session cannot be used again. Remove it from the cache.
SSLSessionContextImpl sessionCache = (SSLSessionContextImpl)
@@ -681,7 +685,7 @@
chc.resumingSession.getTicketCreationTime());
int obfuscatedAge =
ageMillis + chc.resumingSession.getTicketAgeAdd();
- identities.add(new PskIdentity(pskId, obfuscatedAge));
+ identities.add(new PskIdentity(chc.pskIdentity, obfuscatedAge));
SecretKey binderKey = deriveBinderKey(psk, chc.resumingSession);
ClientHelloMessage clientHello = (ClientHelloMessage)message;
diff -r a659ccd1888d -r ddbd9744a3d5 src/java.base/share/classes/sun/security/util/ArrayUtil.java
--- a/src/java.base/share/classes/sun/security/util/ArrayUtil.java Tue Dec 11 11:45:43 2018 +0530
+++ b/src/java.base/share/classes/sun/security/util/ArrayUtil.java Wed Dec 12 15:04:47 2018 +0530
@@ -52,4 +52,21 @@
// NPE is thrown when array is null
Preconditions.checkFromIndexSize(offset, len, array.length, AIOOBE_SUPPLIER);
}
+
+ private static void swap(byte[] arr, int i, int j) {
+ byte tmp = arr[i];
+ arr[i] = arr[j];
+ arr[j] = tmp;
+ }
+
+ public static void reverse(byte [] arr) {
+ int i = 0;
+ int j = arr.length - 1;
+
+ while (i < j) {
+ swap(arr, i, j);
+ i++;
+ j--;
+ }
+ }
}
diff -r a659ccd1888d -r ddbd9744a3d5 src/java.base/share/classes/sun/security/util/math/MutableIntegerModuloP.java
--- a/src/java.base/share/classes/sun/security/util/math/MutableIntegerModuloP.java Tue Dec 11 11:45:43 2018 +0530
+++ b/src/java.base/share/classes/sun/security/util/math/MutableIntegerModuloP.java Wed Dec 12 15:04:47 2018 +0530
@@ -41,6 +41,18 @@
public interface MutableIntegerModuloP extends IntegerModuloP {
/**
+ * Set this value to the value of b when set has the value 1.
+ * No change is made to this element when set has the value 0. The
+ * result is undefined when set has a value other than 0 or 1. The set
+ * parameter is an int (rather than boolean) to allow the implementation
+ * to perform the assignment using branch-free integer arithmetic.
+ *
+ * @param b the element to conditionally swap with
+ * @param set an int that determines whether to set
+ */
+ void conditionalSet(IntegerModuloP b, int set);
+
+ /**
* Swap the value of this with the value of b when swap has the value 1.
* No change is made to either element when swap has the value 0. The
* result is undefined when swap has a value other than 0 or 1. The swap
@@ -131,5 +143,20 @@
* @return this
*/
MutableIntegerModuloP setProduct(SmallValue v);
+
+ /**
+ * Set the value of this element equal to 0 - this.
+ *
+ * @return this
+ */
+ MutableIntegerModuloP setAdditiveInverse();
+
+ /**
+ * Some implementations required reduction operations to be requested
+ * by the client at certain times. This method reduces the representation.
+ *
+ * @return this
+ */
+ MutableIntegerModuloP setReduced();
}
diff -r a659ccd1888d -r ddbd9744a3d5 src/java.base/share/classes/sun/security/util/math/intpoly/FieldGen.jsh
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/util/math/intpoly/FieldGen.jsh Wed Dec 12 15:04:47 2018 +0530
@@ -0,0 +1,851 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * This file is used to generated optimized finite field implementations.
+ * Required settings are included in the file. To generate, use jshell:
+ * jshell < FieldGen.jsh
+ */
+
+import java.io.*;
+import java.math.BigInteger;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.*;
+
+public class FieldGen {
+
+ static FieldParams Curve25519 = new FieldParams("IntegerPolynomial25519", 26, 10, 1, 255,
+ Arrays.asList(
+ new Term(0, -19)
+ ),
+ Curve25519CrSequence(), simpleSmallCrSequence(10)
+ );
+
+ private static List Curve25519CrSequence() {
+ List result = new ArrayList();
+
+ // reduce(7,2)
+ result.add(new Reduce(17));
+ result.add(new Reduce(18));
+
+ // carry(8,2)
+ result.add(new Carry(8));
+ result.add(new Carry(9));
+
+ // reduce(0,7)
+ for (int i = 10; i < 17; i++) {
+ result.add(new Reduce(i));
+ }
+
+ // carry(0,9)
+ result.addAll(fullCarry(10));
+
+ return result;
+ }
+
+ static FieldParams Curve448 = new FieldParams("IntegerPolynomial448", 28, 16, 1, 448,
+ Arrays.asList(
+ new Term(224, -1),
+ new Term(0, -1)
+ ),
+ Curve448CrSequence(), simpleSmallCrSequence(16)
+ );
+
+ private static List Curve448CrSequence() {
+ List result = new ArrayList();
+
+ // reduce(8, 7)
+ for (int i = 24; i < 31; i++) {
+ result.add(new Reduce(i));
+ }
+ // reduce(4, 4)
+ for (int i = 20; i < 24; i++) {
+ result.add(new Reduce(i));
+ }
+
+ //carry(14, 2)
+ result.add(new Carry(14));
+ result.add(new Carry(15));
+
+ // reduce(0, 4)
+ for (int i = 16; i < 20; i++) {
+ result.add(new Reduce(i));
+ }
+
+ // carry(0, 15)
+ result.addAll(fullCarry(16));
+
+ return result;
+ }
+
+ static FieldParams P256 = new FieldParams("IntegerPolynomialP256", 26, 10, 2, 256,
+ Arrays.asList(
+ new Term(224, -1),
+ new Term(192, 1),
+ new Term(96, 1),
+ new Term(0, -1)
+ ),
+ P256CrSequence(), simpleSmallCrSequence(10)
+ );
+
+ private static List P256CrSequence() {
+ List result = new ArrayList();
+ result.addAll(fullReduce(10));
+ result.addAll(simpleSmallCrSequence(10));
+ return result;
+ }
+
+ static FieldParams P384 = new FieldParams("IntegerPolynomialP384", 28, 14, 2, 384,
+ Arrays.asList(
+ new Term(128, -1),
+ new Term(96, -1),
+ new Term(32, 1),
+ new Term(0, -1)
+ ),
+ P384CrSequence(), simpleSmallCrSequence(14)
+ );
+
+ private static List P384CrSequence() {
+ List result = new ArrayList();
+ result.addAll(fullReduce(14));
+ result.addAll(simpleSmallCrSequence(14));
+ return result;
+ }
+
+ static FieldParams P521 = new FieldParams("IntegerPolynomialP521", 28, 19, 2, 521,
+ Arrays.asList(new Term(0, -1)), P521CrSequence(), simpleSmallCrSequence(19)
+ );
+
+ private static List P521CrSequence() {
+ List result = new ArrayList();
+ result.addAll(fullReduce(19));
+ result.addAll(simpleSmallCrSequence(19));
+ return result;
+ }
+
+ static FieldParams O256 = new FieldParams("P256OrderField", 26, 10, 1, 256,
+ new BigInteger("26959946660873538059280334323273029441504803697035324946844617595567"),
+ orderFieldCrSequence(10), orderFieldSmallCrSequence(10)
+ );
+
+ static FieldParams O384 = new FieldParams("P384OrderField", 28, 14, 1, 384,
+ new BigInteger("1388124618062372383947042015309946732620727252194336364173"),
+ orderFieldCrSequence(14), orderFieldSmallCrSequence(14)
+ );
+
+ static FieldParams O521 = new FieldParams("P521OrderField", 28, 19, 1, 521,
+ new BigInteger("657877501894328237357444332315020117536923257219387276263472201219398408051703"),
+ o521crSequence(19), orderFieldSmallCrSequence(19)
+ );
+
+ private static List o521crSequence(int numLimbs) {
+
+ // split the full reduce in half, with a carry in between
+ List result = new ArrayList();
+ result.addAll(fullCarry(2 * numLimbs));
+ for (int i = 2 * numLimbs - 1; i >= numLimbs + numLimbs/2; i--) {
+ result.add(new Reduce(i));
+ }
+ // carry
+ for (int i = numLimbs; i < numLimbs + numLimbs / 2 - 1; i++) {
+ result.add(new Carry(i));
+ }
+ // rest of reduce
+ for (int i = numLimbs + numLimbs/2 - 1; i >= numLimbs; i--) {
+ result.add(new Reduce(i));
+ }
+ result.addAll(orderFieldSmallCrSequence(numLimbs));
+
+ return result;
+ }
+
+ private static List orderFieldCrSequence(int numLimbs) {
+ List result = new ArrayList();
+ result.addAll(fullCarry(2 * numLimbs));
+ result.add(new Reduce(2 * numLimbs - 1));
+ result.addAll(fullReduce(numLimbs));
+ result.addAll(fullCarry(numLimbs + 1));
+ result.add(new Reduce(numLimbs));
+ result.addAll(fullCarry(numLimbs));
+
+ return result;
+ }
+ private static List orderFieldSmallCrSequence(int numLimbs) {
+ List result = new ArrayList();
+ result.addAll(fullCarry(numLimbs + 1));
+ result.add(new Reduce(numLimbs));
+ result.addAll(fullCarry(numLimbs));
+ return result;
+ }
+
+ static final FieldParams[] ALL_FIELDS = {P256, P384, P521, O256, O384, O521};
+
+ public static class Term {
+ private final int power;
+ private final int coefficient;
+
+ public Term(int power, int coefficient) {
+ this.power = power;
+ this.coefficient = coefficient;
+ }
+
+ public int getPower() {
+ return power;
+ }
+
+ public int getCoefficient() {
+ return coefficient;
+ }
+
+ public BigInteger getValue() {
+ return BigInteger.valueOf(2).pow(power).multiply(BigInteger.valueOf(coefficient));
+ }
+
+ }
+
+ static abstract class CarryReduce {
+ private final int index;
+
+ protected CarryReduce(int index) {
+ this.index = index;
+ }
+
+ public int getIndex() {
+ return index;
+ }
+
+ public abstract void write(CodeBuffer out, FieldParams params, String prefix, Iterable remaining);
+ }
+
+ static class Carry extends CarryReduce {
+ public Carry(int index) {
+ super(index);
+ }
+
+ public void write(CodeBuffer out, FieldParams params, String prefix, Iterable remaining) {
+ carry(out, params, prefix, getIndex());
+ }
+ }
+
+ static class Reduce extends CarryReduce {
+ public Reduce(int index) {
+ super(index);
+ }
+
+ public void write(CodeBuffer out, FieldParams params, String prefix, Iterable remaining) {
+ reduce(out, params, prefix, getIndex(), remaining);
+ }
+ }
+
+ static class FieldParams {
+ private final String className;
+ private final int bitsPerLimb;
+ private final int numLimbs;
+ private final int maxAdds;
+ private final int power;
+ private final Iterable terms;
+ private final List crSequence;
+ private final List smallCrSequence;
+
+ public FieldParams(String className, int bitsPerLimb, int numLimbs, int maxAdds, int power,
+ Iterable terms, List crSequence, List smallCrSequence) {
+ this.className = className;
+ this.bitsPerLimb = bitsPerLimb;
+ this.numLimbs = numLimbs;
+ this.maxAdds = maxAdds;
+ this.power = power;
+ this.terms = terms;
+ this.crSequence = crSequence;
+ this.smallCrSequence = smallCrSequence;
+ }
+
+ public FieldParams(String className, int bitsPerLimb, int numLimbs, int maxAdds, int power,
+ BigInteger term, List crSequence, List smallCrSequence) {
+ this.className = className;
+ this.bitsPerLimb = bitsPerLimb;
+ this.numLimbs = numLimbs;
+ this.maxAdds = maxAdds;
+ this.power = power;
+ this.crSequence = crSequence;
+ this.smallCrSequence = smallCrSequence;
+
+ terms = buildTerms(term);
+ }
+
+ private Iterable buildTerms(BigInteger sub) {
+ // split a large subtrahend into smaller terms that are aligned with limbs
+ List result = new ArrayList();
+ BigInteger mod = BigInteger.valueOf(1 << bitsPerLimb);
+ int termIndex = 0;
+ while (!sub.equals(BigInteger.ZERO)) {
+ int coef = sub.mod(mod).intValue();
+ boolean plusOne = false;
+ if (coef > (1 << (bitsPerLimb - 1))) {
+ coef = coef - (1 << bitsPerLimb);
+ plusOne = true;
+ }
+ if (coef != 0) {
+ int pow = termIndex * bitsPerLimb;
+ result.add(new Term(pow, -coef));
+ }
+ sub = sub.shiftRight(bitsPerLimb);
+ if (plusOne) {
+ sub = sub.add(BigInteger.ONE);
+ }
+ ++termIndex;
+ }
+ return result;
+ }
+
+ public String getClassName() {
+ return className;
+ }
+
+ public int getBitsPerLimb() {
+ return bitsPerLimb;
+ }
+
+ public int getNumLimbs() {
+ return numLimbs;
+ }
+
+ public int getMaxAdds() {
+ return maxAdds;
+ }
+
+ public int getPower() {
+ return power;
+ }
+
+ public Iterable getTerms() {
+ return terms;
+ }
+
+ public List getCrSequence() {
+ return crSequence;
+ }
+
+ public List getSmallCrSequence() {
+ return smallCrSequence;
+ }
+ }
+
+ static Collection fullCarry(int numLimbs) {
+ List result = new ArrayList();
+ for (int i = 0; i < numLimbs - 1; i++) {
+ result.add(new Carry(i));
+ }
+ return result;
+ }
+
+ static Collection fullReduce(int numLimbs) {
+ List result = new ArrayList();
+ for (int i = numLimbs - 2; i >= 0; i--) {
+ result.add(new Reduce(i + numLimbs));
+ }
+ return result;
+ }
+
+ static List simpleCrSequence(int numLimbs) {
+ List result = new ArrayList();
+ for(int i = 0; i < 4; i++) {
+ result.addAll(fullCarry(2 * numLimbs - 1));
+ result.addAll(fullReduce(numLimbs));
+ }
+
+ return result;
+ }
+
+ static List simpleSmallCrSequence(int numLimbs) {
+ List result = new ArrayList();
+ // carry a few positions at the end
+ for (int i = numLimbs - 2; i < numLimbs; i++) {
+ result.add(new Carry(i));
+ }
+ // this carries out a single value that must be reduced back in
+ result.add(new Reduce(numLimbs));
+ // finish with a full carry
+ result.addAll(fullCarry(numLimbs));
+ return result;
+ }
+
+ private final String packageName;
+ private final String parentName;
+
+ public FieldGen(String packageName, String parentName) {
+ this.packageName = packageName;
+ this.parentName = parentName;
+ }
+
+ public static void main(String[] args) throws Exception {
+
+ FieldGen gen = new FieldGen("sun.security.util.math.intpoly", "IntegerPolynomial");
+ for(FieldParams p : ALL_FIELDS) {
+ gen.generateFile(p);
+ }
+ }
+
+ private void generateFile(FieldParams params) throws IOException {
+ String text = generate(params);
+ String fileName = params.getClassName() + ".java";
+ PrintWriter out = new PrintWriter(new FileWriter(fileName));
+ out.println(text);
+ out.close();
+ }
+
+ static class CodeBuffer {
+
+ private int nextTemporary = 0;
+ private Set temporaries = new HashSet();
+ private StringBuffer buffer = new StringBuffer();
+ private int indent = 0;
+ private Class lastCR;
+ private int lastCrCount = 0;
+ private int crMethodBreakCount = 0;
+ private int crNumLimbs = 0;
+
+ public void incrIndent() {
+ indent++;
+ }
+
+ public void decrIndent() {
+ indent--;
+ }
+
+ public void newTempScope() {
+ nextTemporary = 0;
+ temporaries.clear();
+ }
+
+ public void appendLine(String s) {
+ appendIndent();
+ buffer.append(s + "\n");
+ }
+
+ public void appendLine() {
+ buffer.append("\n");
+ }
+
+ public String toString() {
+ return buffer.toString();
+ }
+
+ public void startCrSequence(int numLimbs) {
+ this.crNumLimbs = numLimbs;
+ lastCrCount = 0;
+ crMethodBreakCount = 0;
+ lastCR = null;
+ }
+ /*
+ * Record a carry/reduce of the specified type. This method is used to
+ * break up large carry/reduce sequences into multiple methods to make
+ * JIT/optimization easier
+ */
+ public void record(Class type) {
+ if (type == lastCR) {
+ lastCrCount++;
+ } else {
+
+ if (lastCrCount >= 8) {
+ insertCrMethodBreak();
+ }
+
+ lastCR = type;
+ lastCrCount = 0;
+ }
+ }
+
+ private void insertCrMethodBreak() {
+
+ appendLine();
+
+ // call the new method
+ appendIndent();
+ append("carryReduce" + crMethodBreakCount + "(r");
+ for(int i = 0; i < crNumLimbs; i++) {
+ append(", c" + i);
+ }
+ // temporaries are not live between operations, no need to send
+ append(");\n");
+
+ decrIndent();
+ appendLine("}");
+
+ // make the method
+ appendIndent();
+ append("void carryReduce" + crMethodBreakCount + "(long[] r");
+ for(int i = 0; i < crNumLimbs; i++) {
+ append (", long c" + i);
+ }
+ append(") {\n");
+ incrIndent();
+ // declare temporaries
+ for(String temp : temporaries) {
+ appendLine("long " + temp + ";");
+ }
+ append("\n");
+
+ crMethodBreakCount++;
+ }
+
+ public String getTemporary(String type, String value) {
+ Iterator iter = temporaries.iterator();
+ if(iter.hasNext()) {
+ String result = iter.next();
+ iter.remove();
+ appendLine(result + " = " + value + ";");
+ return result;
+ } else {
+ String result = "t" + (nextTemporary++);
+ appendLine(type + " " + result + " = " + value + ";");
+ return result;
+ }
+ }
+
+ public void freeTemporary(String temp) {
+ temporaries.add(temp);
+ }
+
+ public void appendIndent() {
+ for(int i = 0; i < indent; i++) {
+ buffer.append(" ");
+ }
+ }
+
+ public void append(String s) {
+ buffer.append(s);
+ }
+ }
+
+ private String generate(FieldParams params) throws IOException {
+ CodeBuffer result = new CodeBuffer();
+ String header = readHeader();
+ result.appendLine(header);
+
+ if (packageName != null) {
+ result.appendLine("package " + packageName + ";");
+ result.appendLine();
+ }
+ result.appendLine("import java.math.BigInteger;");
+
+ result.appendLine("public class " + params.getClassName() + " extends " + this.parentName + " {");
+ result.incrIndent();
+
+ result.appendLine("private static final int BITS_PER_LIMB = " + params.getBitsPerLimb() + ";");
+ result.appendLine("private static final int NUM_LIMBS = " + params.getNumLimbs() + ";");
+ result.appendLine("private static final int MAX_ADDS = " + params.getMaxAdds() + ";");
+ result.appendLine("public static final BigInteger MODULUS = evaluateModulus();");
+ result.appendLine("private static final long CARRY_ADD = 1 << " + (params.getBitsPerLimb() - 1) + ";");
+ if (params.getBitsPerLimb() * params.getNumLimbs() != params.getPower()) {
+ result.appendLine("private static final int LIMB_MASK = -1 >>> (64 - BITS_PER_LIMB);");
+ }
+ int termIndex = 0;
+
+ result.appendLine("public " + params.getClassName() + "() {");
+ result.appendLine();
+ result.appendLine(" super(BITS_PER_LIMB, NUM_LIMBS, MAX_ADDS, MODULUS);");
+ result.appendLine();
+ result.appendLine("}");
+
+ result.appendLine("private static BigInteger evaluateModulus() {");
+ result.incrIndent();
+ result.appendLine("BigInteger result = BigInteger.valueOf(2).pow(" + params.getPower() + ");");
+ for(Term t : params.getTerms()) {
+ boolean subtract = false;
+ int coefValue = t.getCoefficient();
+ if (coefValue < 0) {
+ coefValue = 0 - coefValue;
+ subtract = true;
+ }
+ String coefExpr = "BigInteger.valueOf(" + coefValue + ")";
+ String powExpr = "BigInteger.valueOf(2).pow(" + t.getPower() + ")";
+ String termExpr = "ERROR";
+ if (t.getPower() == 0) {
+ termExpr = coefExpr;
+ } else if (coefValue == 1) {
+ termExpr = powExpr;
+ } else {
+ termExpr = powExpr + ".multiply(" + coefExpr + ")";
+ }
+ if (subtract) {
+ result.appendLine("result = result.subtract(" + termExpr + ");");
+ } else {
+ result.appendLine("result = result.add(" + termExpr + ");");
+ }
+ }
+ result.appendLine("return result;");
+ result.decrIndent();
+ result.appendLine("}");
+
+ result.appendLine("@Override");
+ result.appendLine("protected void finalCarryReduceLast(long[] limbs) {");
+ result.incrIndent();
+ int extraBits = params.getBitsPerLimb() * params.getNumLimbs() - params.getPower();
+ int highBits = params.getBitsPerLimb() - extraBits;
+ result.appendLine("long c = limbs[" + (params.getNumLimbs() - 1) + "] >> " + highBits + ";");
+ result.appendLine("limbs[" + (params.getNumLimbs() - 1) + "] -= c << " + highBits + ";");
+ for (Term t : params.getTerms()) {
+ int reduceBits = params.getPower() + extraBits - t.getPower();
+ int negatedCoefficient = -1 * t.getCoefficient();
+ modReduceInBits(result, params, true, "limbs", params.getNumLimbs(), reduceBits, negatedCoefficient, "c");
+ }
+ result.decrIndent();
+ result.appendLine("}");
+
+ // full carry/reduce sequence
+ result.appendIndent();
+ result.append("private void carryReduce(long[] r, ");
+ for(int i = 0; i < 2 * params.getNumLimbs() - 1; i++) {
+ result.append ("long c" + i);
+ if (i < 2 * params.getNumLimbs() - 2) {
+ result.append(", ");
+ }
+ }
+ result.append(") {\n");
+ result.newTempScope();
+ result.incrIndent();
+ result.appendLine("long c" + (2 * params.getNumLimbs() - 1) + " = 0;");
+ write(result, params.getCrSequence(), params, "c", 2 * params.getNumLimbs());
+ result.appendLine();
+ for (int i = 0; i < params.getNumLimbs(); i++) {
+ result.appendLine("r[" + i + "] = c" + i + ";");
+ }
+ result.decrIndent();
+ result.appendLine("}");
+
+ // small carry/reduce sequence
+ result.appendIndent();
+ result.append("private void carryReduce(long[] r, ");
+ for(int i = 0; i < params.getNumLimbs(); i++) {
+ result.append ("long c" + i);
+ if (i < params.getNumLimbs() - 1) {
+ result.append(", ");
+ }
+ }
+ result.append(") {\n");
+ result.newTempScope();
+ result.incrIndent();
+ result.appendLine("long c" + params.getNumLimbs() + " = 0;");
+ write(result, params.getSmallCrSequence(), params, "c", params.getNumLimbs() + 1);
+ result.appendLine();
+ for (int i = 0; i < params.getNumLimbs(); i++) {
+ result.appendLine("r[" + i + "] = c" + i + ";");
+ }
+ result.decrIndent();
+ result.appendLine("}");
+
+ result.appendLine("@Override");
+ result.appendLine("protected void mult(long[] a, long[] b, long[] r) {");
+ result.incrIndent();
+ for (int i = 0; i < 2 * params.getNumLimbs() - 1; i++) {
+ result.appendIndent();
+ result.append("long c" + i + " = ");
+ int startJ = Math.max(i + 1 - params.getNumLimbs(), 0);
+ int endJ = Math.min(params.getNumLimbs(), i + 1);
+ for (int j = startJ; j < endJ; j++) {
+ int bIndex = i - j;
+ result.append("(a[" + j + "] * b[" + bIndex + "])");
+ if (j < endJ - 1) {
+ result.append(" + ");
+ }
+ }
+ result.append(";\n");
+ }
+ result.appendLine();
+ result.appendIndent();
+ result.append("carryReduce(r, ");
+ for (int i = 0; i < 2 * params.getNumLimbs() - 1; i++) {
+ result.append("c" + i);
+ if (i < 2 * params.getNumLimbs() - 2) {
+ result.append(", ");
+ }
+ }
+ result.append(");\n");
+ result.decrIndent();
+ result.appendLine("}");
+
+ result.appendLine("@Override");
+ result.appendLine("protected void reduce(long[] a) {");
+ result.incrIndent();
+ result.appendIndent();
+ result.append("carryReduce(a, ");
+ for (int i = 0; i < params.getNumLimbs(); i++) {
+ result.append("a[" + i + "]");
+ if (i < params.getNumLimbs() - 1) {
+ result.append(", ");
+ }
+ }
+ result.append(");\n");
+ result.decrIndent();
+ result.appendLine("}");
+
+ result.appendLine("@Override");
+ result.appendLine("protected void square(long[] a, long[] r) {");
+ result.incrIndent();
+ for (int i = 0; i < 2 * params.getNumLimbs() - 1; i++) {
+ result.appendIndent();
+ result.append("long c" + i + " = ");
+ int startJ = Math.max(i + 1 - params.getNumLimbs(), 0);
+ int endJ = Math.min(params.getNumLimbs(), i + 1);
+ int jDiff = endJ - startJ;
+ if (jDiff > 1) {
+ result.append("2 * (");
+ }
+ for (int j = 0; j < jDiff / 2; j++) {
+ int aIndex = j + startJ;
+ int bIndex = i - aIndex;
+ result.append("(a[" + aIndex + "] * a[" + bIndex + "])");
+ if (j < (jDiff / 2) - 1) {
+ result.append(" + ");
+ }
+ }
+ if (jDiff > 1) {
+ result.append(")");
+ }
+ if (jDiff % 2 == 1) {
+ int aIndex = i / 2;
+ if (jDiff > 1) {
+ result.append (" + ");
+ }
+ result.append("(a[" + aIndex + "] * a[" + aIndex + "])");
+ }
+ result.append(";\n");
+ }
+ result.appendLine();
+ result.appendIndent();
+ result.append("carryReduce(r, ");
+ for (int i = 0; i < 2 * params.getNumLimbs() - 1; i++) {
+ result.append("c" + i);
+ if (i < 2 * params.getNumLimbs() - 2) {
+ result.append(", ");
+ }
+ }
+ result.append(");\n");
+ result.decrIndent();
+ result.appendLine("}");
+
+ result.decrIndent();
+ result.appendLine("}"); // end class
+
+ return result.toString();
+ }
+
+ private static void write(CodeBuffer out, List sequence, FieldParams params, String prefix, int numLimbs) {
+
+ out.startCrSequence(numLimbs);
+ for (int i = 0; i < sequence.size(); i++) {
+ CarryReduce cr = sequence.get(i);
+ Iterator remainingIter = sequence.listIterator(i + 1);
+ List remaining = new ArrayList();
+ remainingIter.forEachRemaining(remaining::add);
+ cr.write(out, params, prefix, remaining);
+ }
+ }
+
+ private static void reduce(CodeBuffer out, FieldParams params, String prefix, int index, Iterable remaining) {
+
+ out.record(Reduce.class);
+
+ out.appendLine("//reduce from position " + index);
+ String reduceFrom = indexedExpr(false, prefix, index);
+ boolean referenced = false;
+ for (CarryReduce cr : remaining) {
+ if(cr.index == index) {
+ referenced = true;
+ }
+ }
+ for (Term t : params.getTerms()) {
+ int reduceBits = params.getPower() - t.getPower();
+ int negatedCoefficient = -1 * t.getCoefficient();
+ modReduceInBits(out, params, false, prefix, index, reduceBits, negatedCoefficient, reduceFrom);
+ }
+ if (referenced) {
+ out.appendLine(reduceFrom + " = 0;");
+ }
+ }
+
+ private static void carry(CodeBuffer out, FieldParams params, String prefix, int index) {
+
+ out.record(Carry.class);
+
+ out.appendLine("//carry from position " + index);
+ String carryFrom = prefix + index;
+ String carryTo = prefix + (index + 1);
+ String carry = "(" + carryFrom + " + CARRY_ADD) >> " + params.getBitsPerLimb();
+ String temp = out.getTemporary("long", carry);
+ out.appendLine(carryFrom + " -= (" + temp + " << " + params.getBitsPerLimb() + ");");
+ out.appendLine(carryTo + " += " + temp + ";");
+ out.freeTemporary(temp);
+ }
+
+ private static String indexedExpr(boolean isArray, String prefix, int index) {
+ String result = prefix + index;
+ if (isArray) {
+ result = prefix + "[" + index + "]";
+ }
+ return result;
+ }
+
+ private static void modReduceInBits(CodeBuffer result, FieldParams params, boolean isArray, String prefix, int index, int reduceBits, int coefficient, String c) {
+
+ String x = coefficient + " * " + c;
+ String accOp = "+=";
+ String temp = null;
+ if (coefficient == 1) {
+ x = c;
+ } else if (coefficient == -1) {
+ x = c;
+ accOp = "-=";
+ } else {
+ temp = result.getTemporary("long", x);
+ x = temp;
+ }
+
+ if (reduceBits % params.getBitsPerLimb() == 0) {
+ int pos = reduceBits / params.getBitsPerLimb();
+ result.appendLine(indexedExpr(isArray, prefix, (index - pos)) + " " + accOp + " " + x + ";");
+ } else {
+ int secondPos = reduceBits / params.getBitsPerLimb();
+ int bitOffset = (secondPos + 1) * params.getBitsPerLimb() - reduceBits;
+ int rightBitOffset = params.getBitsPerLimb() - bitOffset;
+ result.appendLine(indexedExpr(isArray, prefix, (index - (secondPos + 1))) + " " + accOp + " (" + x + " << " + bitOffset + ") & LIMB_MASK;");
+ result.appendLine(indexedExpr(isArray, prefix, (index - secondPos)) + " " + accOp + " " + x + " >> " + rightBitOffset + ";");
+ }
+
+ if (temp != null) {
+ result.freeTemporary(temp);
+ }
+ }
+
+ private String readHeader() throws IOException {
+ BufferedReader reader = Files.newBufferedReader(Paths.get("header.txt"));
+ StringBuffer result = new StringBuffer();
+ reader.lines().forEach(s -> result.append(s + "\n"));
+ return result.toString();
+ }
+}
+
+FieldGen.main(null);
+
diff -r a659ccd1888d -r ddbd9744a3d5 src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial.java
--- a/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial.java Tue Dec 11 11:45:43 2018 +0530
+++ b/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial.java Wed Dec 12 15:04:47 2018 +0530
@@ -69,14 +69,25 @@
private final BigInteger modulus;
protected final int bitsPerLimb;
private final long[] posModLimbs;
+ private final int maxAdds;
+
+ /**
+ * Reduce an IntegerPolynomial representation (a) and store the result
+ * in a. Requires that a.length == numLimbs.
+ */
+ protected abstract void reduce(long[] a);
/**
* Multiply an IntegerPolynomial representation (a) with a long (b) and
- * store the result in an IntegerPolynomial representation (r). Requires
- * that a.length == r.length == numLimbs. It is allowed for a and r to be
- * the same array.
+ * store the result in an IntegerPolynomial representation in a. Requires
+ * that a.length == numLimbs.
*/
- protected abstract void multByInt(long[] a, long b, long[] r);
+ protected void multByInt(long[] a, long b) {
+ for (int i = 0; i < a.length; i++) {
+ a[i] *= b;
+ }
+ reduce(a);
+ }
/**
* Multiply two IntegerPolynomial representations (a and b) and store the
@@ -96,12 +107,14 @@
IntegerPolynomial(int bitsPerLimb,
int numLimbs,
+ int maxAdds,
BigInteger modulus) {
this.numLimbs = numLimbs;
this.modulus = modulus;
this.bitsPerLimb = bitsPerLimb;
+ this.maxAdds = maxAdds;
posModLimbs = setPosModLimbs();
}
@@ -116,6 +129,10 @@
return numLimbs;
}
+ public int getMaxAdds() {
+ return maxAdds;
+ }
+
@Override
public BigInteger getSize() {
return modulus;
@@ -155,12 +172,22 @@
*/
protected void encode(ByteBuffer buf, int length, byte highByte,
long[] result) {
+
int numHighBits = 32 - Integer.numberOfLeadingZeros(highByte);
int numBits = 8 * length + numHighBits;
- int maxBits = bitsPerLimb * result.length;
- if (numBits > maxBits) {
- throw new ArithmeticException("Value is too large.");
+ int requiredLimbs = (numBits + bitsPerLimb - 1) / bitsPerLimb;
+ if (requiredLimbs > numLimbs) {
+ long[] temp = new long[requiredLimbs];
+ encodeSmall(buf, length, highByte, temp);
+ // encode does a full carry/reduce
+ System.arraycopy(temp, 0, result, 0, result.length);
+ } else {
+ encodeSmall(buf, length, highByte, result);
}
+ }
+
+ protected void encodeSmall(ByteBuffer buf, int length, byte highByte,
+ long[] result) {
int limbIndex = 0;
long curLimbValue = 0;
@@ -195,10 +222,10 @@
}
}
- if (limbIndex < numLimbs) {
+ if (limbIndex < result.length) {
result[limbIndex++] = curLimbValue;
}
- Arrays.fill(result, limbIndex, numLimbs, 0);
+ Arrays.fill(result, limbIndex, result.length, 0);
postEncodeCarry(result);
}
@@ -211,8 +238,10 @@
encode(buf, length, highByte, result);
}
+ // Encode does not produce compressed limbs. A simplified carry/reduce
+ // operation can be used to compress the limbs.
protected void postEncodeCarry(long[] v) {
- carry(v);
+ reduce(v);
}
public ImmutableElement getElement(byte[] v, int offset, int length,
@@ -222,7 +251,7 @@
encode(v, offset, length, highByte, result);
- return new ImmutableElement(result, true);
+ return new ImmutableElement(result, 0);
}
protected BigInteger evaluate(long[] limbs) {
@@ -387,6 +416,20 @@
}
/**
+ * Branch-free conditional assignment of b to a. Requires that set is 0 or
+ * 1, and that a.length == b.length. If set==0, then the values of a and b
+ * will be unchanged. If set==1, then the values of b will be assigned to a.
+ * The behavior is undefined if swap has any value other than 0 or 1.
+ */
+ protected static void conditionalAssign(int set, long[] a, long[] b) {
+ int maskValue = 0 - set;
+ for (int i = 0; i < a.length; i++) {
+ long dummyLimbs = maskValue & (a[i] ^ b[i]);
+ a[i] = dummyLimbs ^ a[i];
+ }
+ }
+
+ /**
* Branch-free conditional swap of a and b. Requires that swap is 0 or 1,
* and that a.length == b.length. If swap==0, then the values of a and b
* will be unchanged. If swap==1, then the values of a and b will be
@@ -442,7 +485,7 @@
private abstract class Element implements IntegerModuloP {
protected long[] limbs;
- protected boolean summand = false;
+ protected int numAdds;
public Element(BigInteger v) {
limbs = new long[numLimbs];
@@ -450,19 +493,19 @@
}
public Element(boolean v) {
- limbs = new long[numLimbs];
- limbs[0] = v ? 1l : 0l;
- summand = true;
+ this.limbs = new long[numLimbs];
+ this.limbs[0] = v ? 1l : 0l;
+ this.numAdds = 0;
}
- private Element(long[] limbs, boolean summand) {
+ private Element(long[] limbs, int numAdds) {
this.limbs = limbs;
- this.summand = summand;
+ this.numAdds = numAdds;
}
private void setValue(BigInteger v) {
setLimbsValue(v, limbs);
- summand = true;
+ this.numAdds = 0;
}
@Override
@@ -477,14 +520,18 @@
@Override
public MutableElement mutable() {
- return new MutableElement(limbs.clone(), summand);
+ return new MutableElement(limbs.clone(), numAdds);
+ }
+
+ protected boolean isSummand() {
+ return numAdds < maxAdds;
}
@Override
public ImmutableElement add(IntegerModuloP genB) {
Element b = (Element) genB;
- if (!(summand && b.summand)) {
+ if (!(isSummand() && b.isSummand())) {
throw new ArithmeticException("Not a valid summand");
}
@@ -493,7 +540,8 @@
newLimbs[i] = limbs[i] + b.limbs[i];
}
- return new ImmutableElement(newLimbs, false);
+ int newNumAdds = Math.max(numAdds, b.numAdds) + 1;
+ return new ImmutableElement(newLimbs, newNumAdds);
}
@Override
@@ -504,7 +552,7 @@
newLimbs[i] = -limbs[i];
}
- ImmutableElement result = new ImmutableElement(newLimbs, summand);
+ ImmutableElement result = new ImmutableElement(newLimbs, numAdds);
return result;
}
@@ -524,43 +572,52 @@
long[] newLimbs = new long[limbs.length];
mult(limbs, b.limbs, newLimbs);
- return new ImmutableElement(newLimbs, true);
+ return new ImmutableElement(newLimbs, 0);
}
@Override
public ImmutableElement square() {
long[] newLimbs = new long[limbs.length];
IntegerPolynomial.this.square(limbs, newLimbs);
- return new ImmutableElement(newLimbs, true);
+ return new ImmutableElement(newLimbs, 0);
}
public void addModPowerTwo(IntegerModuloP arg, byte[] result) {
Element other = (Element) arg;
- if (!(summand && other.summand)) {
+ if (!(isSummand() && other.isSummand())) {
throw new ArithmeticException("Not a valid summand");
}
addLimbsModPowerTwo(limbs, other.limbs, result);
}
public void asByteArray(byte[] result) {
- if (!summand) {
+ if (!isSummand()) {
throw new ArithmeticException("Not a valid summand");
}
limbsToByteArray(limbs, result);
}
}
- private class MutableElement extends Element
+ protected class MutableElement extends Element
implements MutableIntegerModuloP {
- protected MutableElement(long[] limbs, boolean summand) {
- super(limbs, summand);
+ protected MutableElement(long[] limbs, int numAdds) {
+ super(limbs, numAdds);
}
@Override
public ImmutableElement fixed() {
- return new ImmutableElement(limbs.clone(), summand);
+ return new ImmutableElement(limbs.clone(), numAdds);
+ }
+
+ @Override
+ public void conditionalSet(IntegerModuloP b, int set) {
+
+ Element other = (Element) b;
+
+ conditionalAssign(set, limbs, other.limbs);
+ numAdds = other.numAdds;
}
@Override
@@ -569,9 +626,9 @@
MutableElement other = (MutableElement) b;
conditionalSwap(swap, limbs, other.limbs);
- boolean summandTemp = summand;
- summand = other.summand;
- other.summand = summandTemp;
+ int numAddsTemp = numAdds;
+ numAdds = other.numAdds;
+ other.numAdds = numAddsTemp;
}
@@ -580,7 +637,7 @@
Element other = (Element) v;
System.arraycopy(other.limbs, 0, limbs, 0, other.limbs.length);
- summand = other.summand;
+ numAdds = other.numAdds;
return this;
}
@@ -589,7 +646,7 @@
int length, byte highByte) {
encode(arr, offset, length, highByte, limbs);
- summand = true;
+ this.numAdds = 0;
return this;
}
@@ -599,7 +656,7 @@
byte highByte) {
encode(buf, length, highByte, limbs);
- summand = true;
+ numAdds = 0;
return this;
}
@@ -608,15 +665,15 @@
public MutableElement setProduct(IntegerModuloP genB) {
Element b = (Element) genB;
mult(limbs, b.limbs, limbs);
- summand = true;
+ numAdds = 0;
return this;
}
@Override
public MutableElement setProduct(SmallValue v) {
int value = ((Limb) v).value;
- multByInt(limbs, value, limbs);
- summand = true;
+ multByInt(limbs, value);
+ numAdds = 0;
return this;
}
@@ -624,7 +681,7 @@
public MutableElement setSum(IntegerModuloP genB) {
Element b = (Element) genB;
- if (!(summand && b.summand)) {
+ if (!(isSummand() && b.isSummand())) {
throw new ArithmeticException("Not a valid summand");
}
@@ -632,7 +689,7 @@
limbs[i] = limbs[i] + b.limbs[i];
}
- summand = false;
+ numAdds = Math.max(numAdds, b.numAdds) + 1;
return this;
}
@@ -640,7 +697,7 @@
public MutableElement setDifference(IntegerModuloP genB) {
Element b = (Element) genB;
- if (!(summand && b.summand)) {
+ if (!(isSummand() && b.isSummand())) {
throw new ArithmeticException("Not a valid summand");
}
@@ -648,16 +705,33 @@
limbs[i] = limbs[i] - b.limbs[i];
}
+ numAdds = Math.max(numAdds, b.numAdds) + 1;
return this;
}
@Override
public MutableElement setSquare() {
IntegerPolynomial.this.square(limbs, limbs);
- summand = true;
+ numAdds = 0;
return this;
}
+ @Override
+ public MutableElement setAdditiveInverse() {
+
+ for (int i = 0; i < limbs.length; i++) {
+ limbs[i] = -limbs[i];
+ }
+ return this;
+ }
+
+ @Override
+ public MutableElement setReduced() {
+
+ reduce(limbs);
+ numAdds = 0;
+ return this;
+ }
}
class ImmutableElement extends Element implements ImmutableIntegerModuloP {
@@ -670,8 +744,8 @@
super(v);
}
- protected ImmutableElement(long[] limbs, boolean summand) {
- super(limbs, summand);
+ protected ImmutableElement(long[] limbs, int numAdds) {
+ super(limbs, numAdds);
}
@Override
diff -r a659ccd1888d -r ddbd9744a3d5 src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial1305.java
--- a/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial1305.java Tue Dec 11 11:45:43 2018 +0530
+++ b/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial1305.java Wed Dec 12 15:04:47 2018 +0530
@@ -45,7 +45,7 @@
= TWO.pow(POWER).subtract(BigInteger.valueOf(SUBTRAHEND));
public IntegerPolynomial1305() {
- super(BITS_PER_LIMB, NUM_LIMBS, MODULUS);
+ super(BITS_PER_LIMB, NUM_LIMBS, 1, MODULUS);
}
protected void mult(long[] a, long[] b, long[] r) {
@@ -96,15 +96,6 @@
carry(r);
}
- protected void multByInt(long[] a, long b, long[] r) {
-
- for (int i = 0; i < a.length; i++) {
- r[i] = a[i] * b;
- }
-
- reduce(r);
- }
-
@Override
protected void square(long[] a, long[] r) {
// Use grade-school multiplication with a simple squaring optimization.
@@ -199,7 +190,12 @@
return x >> BITS_PER_LIMB;
}
+ @Override
+ protected void postEncodeCarry(long[] v) {
+ // not needed because carry is unsigned
+ }
+ @Override
protected void reduce(long[] limbs) {
long carry3 = carryOut(limbs, 3);
long new4 = carry3 + limbs[4];
diff -r a659ccd1888d -r ddbd9744a3d5 src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial25519.java
--- a/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial25519.java Tue Dec 11 11:45:43 2018 +0530
+++ b/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial25519.java Wed Dec 12 15:04:47 2018 +0530
@@ -48,7 +48,7 @@
private static final int RIGHT_BIT_OFFSET = BITS_PER_LIMB - BIT_OFFSET;
public IntegerPolynomial25519() {
- super(BITS_PER_LIMB, NUM_LIMBS, MODULUS);
+ super(BITS_PER_LIMB, NUM_LIMBS, 1, MODULUS);
}
@Override
@@ -60,6 +60,26 @@
}
@Override
+ protected void reduce(long[] a) {
+
+ // carry(8, 2)
+ long carry8 = carryValue(a[8]);
+ a[8] -= (carry8 << BITS_PER_LIMB);
+ a[9] += carry8;
+
+ long carry9 = carryValue(a[9]);
+ a[9] -= (carry9 << BITS_PER_LIMB);
+
+ // reduce(0, 1)
+ long reducedValue10 = (carry9 * SUBTRAHEND);
+ a[0] += ((reducedValue10 << BIT_OFFSET) & LIMB_MASK);
+ a[1] += reducedValue10 >> RIGHT_BIT_OFFSET;
+
+ // carry(0, 9)
+ carry(a, 0, 9);
+ }
+
+ @Override
protected void mult(long[] a, long[] b, long[] r) {
// Use grade-school multiplication into primitives to avoid the
@@ -153,28 +173,6 @@
carry(r, 0, 9);
}
- protected void multByInt(long[] a, long b, long[] r) {
- for (int i = 0; i < a.length; i++) {
- r[i] = a[i] * b;
- }
-
- // carry(8, 2)
- long carry8 = carryValue(r[8]);
- r[8] -= (carry8 << BITS_PER_LIMB);
- r[9] += carry8;
-
- long carry9 = carryValue(r[9]);
- r[9] -= (carry9 << BITS_PER_LIMB);
-
- // reduce(0, 1)
- long reducedValue10 = (carry9 * SUBTRAHEND);
- r[0] += ((reducedValue10 << BIT_OFFSET) & LIMB_MASK);
- r[1] += reducedValue10 >> RIGHT_BIT_OFFSET;
-
- // carry(0, 9)
- carry(r, 0, 9);
- }
-
@Override
protected void square(long[] a, long[] r) {
diff -r a659ccd1888d -r ddbd9744a3d5 src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial448.java
--- a/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial448.java Tue Dec 11 11:45:43 2018 +0530
+++ b/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial448.java Wed Dec 12 15:04:47 2018 +0530
@@ -42,7 +42,7 @@
.subtract(BigInteger.valueOf(1));
public IntegerPolynomial448() {
- super(BITS_PER_LIMB, NUM_LIMBS, MODULUS);
+ super(BITS_PER_LIMB, NUM_LIMBS, 1, MODULUS);
}
private void modReduceIn(long[] limbs, int index, long x) {
@@ -58,6 +58,25 @@
}
@Override
+ protected void reduce(long[] a) {
+
+ // carry(14, 2)
+ long carry14 = carryValue(a[14]);
+ a[14] -= (carry14 << BITS_PER_LIMB);
+ a[15] += carry14;
+
+ long carry15 = carryValue(a[15]);
+ a[15] -= (carry15 << BITS_PER_LIMB);
+
+ // reduce(0, 1)
+ a[0] += carry15;
+ a[8] += carry15;
+
+ // carry(0, 15)
+ carry(a, 0, 15);
+ }
+
+ @Override
protected void mult(long[] a, long[] b, long[] r) {
// Use grade-school multiplication into primitives to avoid the
@@ -176,27 +195,6 @@
carry(r, 0, 15);
}
- protected void multByInt(long[] a, long b, long[] r) {
- for (int i = 0; i < a.length; i++) {
- r[i] = a[i] * b;
- }
-
- // carry(14, 2)
- long carry14 = carryValue(r[14]);
- r[14] -= (carry14 << BITS_PER_LIMB);
- r[15] += carry14;
-
- long carry15 = carryValue(r[15]);
- r[15] -= (carry15 << BITS_PER_LIMB);
-
- // reduce(0, 1)
- r[0] += carry15;
- r[8] += carry15;
-
- // carry(0, 15)
- carry(r, 0, 15);
- }
-
@Override
protected void square(long[] a, long[] r) {
diff -r a659ccd1888d -r ddbd9744a3d5 src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomialP256.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomialP256.java Wed Dec 12 15:04:47 2018 +0530
@@ -0,0 +1,339 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is generated by FieldGen.jsh. Do not modify it directly.
+ */
+
+package sun.security.util.math.intpoly;
+
+import java.math.BigInteger;
+public class IntegerPolynomialP256 extends IntegerPolynomial {
+ private static final int BITS_PER_LIMB = 26;
+ private static final int NUM_LIMBS = 10;
+ private static final int MAX_ADDS = 2;
+ public static final BigInteger MODULUS = evaluateModulus();
+ private static final long CARRY_ADD = 1 << 25;
+ private static final int LIMB_MASK = -1 >>> (64 - BITS_PER_LIMB);
+ public IntegerPolynomialP256() {
+
+ super(BITS_PER_LIMB, NUM_LIMBS, MAX_ADDS, MODULUS);
+
+ }
+ private static BigInteger evaluateModulus() {
+ BigInteger result = BigInteger.valueOf(2).pow(256);
+ result = result.subtract(BigInteger.valueOf(2).pow(224));
+ result = result.add(BigInteger.valueOf(2).pow(192));
+ result = result.add(BigInteger.valueOf(2).pow(96));
+ result = result.subtract(BigInteger.valueOf(1));
+ return result;
+ }
+ @Override
+ protected void finalCarryReduceLast(long[] limbs) {
+ long c = limbs[9] >> 22;
+ limbs[9] -= c << 22;
+ limbs[8] += (c << 16) & LIMB_MASK;
+ limbs[9] += c >> 10;
+ limbs[7] -= (c << 10) & LIMB_MASK;
+ limbs[8] -= c >> 16;
+ limbs[3] -= (c << 18) & LIMB_MASK;
+ limbs[4] -= c >> 8;
+ limbs[0] += c;
+ }
+ private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18) {
+ long c19 = 0;
+ //reduce from position 18
+ c16 += (c18 << 20) & LIMB_MASK;
+ c17 += c18 >> 6;
+ c15 -= (c18 << 14) & LIMB_MASK;
+ c16 -= c18 >> 12;
+ c11 -= (c18 << 22) & LIMB_MASK;
+ c12 -= c18 >> 4;
+ c8 += (c18 << 4) & LIMB_MASK;
+ c9 += c18 >> 22;
+ //reduce from position 17
+ c15 += (c17 << 20) & LIMB_MASK;
+ c16 += c17 >> 6;
+ c14 -= (c17 << 14) & LIMB_MASK;
+ c15 -= c17 >> 12;
+ c10 -= (c17 << 22) & LIMB_MASK;
+ c11 -= c17 >> 4;
+ c7 += (c17 << 4) & LIMB_MASK;
+ c8 += c17 >> 22;
+ //reduce from position 16
+ c14 += (c16 << 20) & LIMB_MASK;
+ c15 += c16 >> 6;
+ c13 -= (c16 << 14) & LIMB_MASK;
+ c14 -= c16 >> 12;
+ c9 -= (c16 << 22) & LIMB_MASK;
+ c10 -= c16 >> 4;
+ c6 += (c16 << 4) & LIMB_MASK;
+ c7 += c16 >> 22;
+ //reduce from position 15
+ c13 += (c15 << 20) & LIMB_MASK;
+ c14 += c15 >> 6;
+ c12 -= (c15 << 14) & LIMB_MASK;
+ c13 -= c15 >> 12;
+ c8 -= (c15 << 22) & LIMB_MASK;
+ c9 -= c15 >> 4;
+ c5 += (c15 << 4) & LIMB_MASK;
+ c6 += c15 >> 22;
+ //reduce from position 14
+ c12 += (c14 << 20) & LIMB_MASK;
+ c13 += c14 >> 6;
+ c11 -= (c14 << 14) & LIMB_MASK;
+ c12 -= c14 >> 12;
+ c7 -= (c14 << 22) & LIMB_MASK;
+ c8 -= c14 >> 4;
+ c4 += (c14 << 4) & LIMB_MASK;
+ c5 += c14 >> 22;
+ //reduce from position 13
+ c11 += (c13 << 20) & LIMB_MASK;
+ c12 += c13 >> 6;
+ c10 -= (c13 << 14) & LIMB_MASK;
+ c11 -= c13 >> 12;
+ c6 -= (c13 << 22) & LIMB_MASK;
+ c7 -= c13 >> 4;
+ c3 += (c13 << 4) & LIMB_MASK;
+ c4 += c13 >> 22;
+ //reduce from position 12
+ c10 += (c12 << 20) & LIMB_MASK;
+ c11 += c12 >> 6;
+ c9 -= (c12 << 14) & LIMB_MASK;
+ c10 -= c12 >> 12;
+ c5 -= (c12 << 22) & LIMB_MASK;
+ c6 -= c12 >> 4;
+ c2 += (c12 << 4) & LIMB_MASK;
+ c3 += c12 >> 22;
+ //reduce from position 11
+ c9 += (c11 << 20) & LIMB_MASK;
+ c10 += c11 >> 6;
+ c8 -= (c11 << 14) & LIMB_MASK;
+ c9 -= c11 >> 12;
+ c4 -= (c11 << 22) & LIMB_MASK;
+ c5 -= c11 >> 4;
+ c1 += (c11 << 4) & LIMB_MASK;
+ c2 += c11 >> 22;
+ //reduce from position 10
+ c8 += (c10 << 20) & LIMB_MASK;
+ c9 += c10 >> 6;
+ c7 -= (c10 << 14) & LIMB_MASK;
+ c8 -= c10 >> 12;
+ c3 -= (c10 << 22) & LIMB_MASK;
+ c4 -= c10 >> 4;
+ c0 += (c10 << 4) & LIMB_MASK;
+ c1 += c10 >> 22;
+ c10 = 0;
+
+ carryReduce0(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19);
+ }
+ void carryReduce0(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19) {
+
+ //carry from position 8
+ long t0 = (c8 + CARRY_ADD) >> 26;
+ c8 -= (t0 << 26);
+ c9 += t0;
+ //carry from position 9
+ t0 = (c9 + CARRY_ADD) >> 26;
+ c9 -= (t0 << 26);
+ c10 += t0;
+ //reduce from position 10
+ c8 += (c10 << 20) & LIMB_MASK;
+ c9 += c10 >> 6;
+ c7 -= (c10 << 14) & LIMB_MASK;
+ c8 -= c10 >> 12;
+ c3 -= (c10 << 22) & LIMB_MASK;
+ c4 -= c10 >> 4;
+ c0 += (c10 << 4) & LIMB_MASK;
+ c1 += c10 >> 22;
+ //carry from position 0
+ t0 = (c0 + CARRY_ADD) >> 26;
+ c0 -= (t0 << 26);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 26;
+ c1 -= (t0 << 26);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 26;
+ c2 -= (t0 << 26);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 26;
+ c3 -= (t0 << 26);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 26;
+ c4 -= (t0 << 26);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 26;
+ c5 -= (t0 << 26);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 26;
+ c6 -= (t0 << 26);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 26;
+ c7 -= (t0 << 26);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 26;
+ c8 -= (t0 << 26);
+ c9 += t0;
+
+ r[0] = c0;
+ r[1] = c1;
+ r[2] = c2;
+ r[3] = c3;
+ r[4] = c4;
+ r[5] = c5;
+ r[6] = c6;
+ r[7] = c7;
+ r[8] = c8;
+ r[9] = c9;
+ }
+ private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9) {
+ long c10 = 0;
+ //carry from position 8
+ long t0 = (c8 + CARRY_ADD) >> 26;
+ c8 -= (t0 << 26);
+ c9 += t0;
+ //carry from position 9
+ t0 = (c9 + CARRY_ADD) >> 26;
+ c9 -= (t0 << 26);
+ c10 += t0;
+ //reduce from position 10
+ c8 += (c10 << 20) & LIMB_MASK;
+ c9 += c10 >> 6;
+ c7 -= (c10 << 14) & LIMB_MASK;
+ c8 -= c10 >> 12;
+ c3 -= (c10 << 22) & LIMB_MASK;
+ c4 -= c10 >> 4;
+ c0 += (c10 << 4) & LIMB_MASK;
+ c1 += c10 >> 22;
+ //carry from position 0
+ t0 = (c0 + CARRY_ADD) >> 26;
+ c0 -= (t0 << 26);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 26;
+ c1 -= (t0 << 26);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 26;
+ c2 -= (t0 << 26);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 26;
+ c3 -= (t0 << 26);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 26;
+ c4 -= (t0 << 26);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 26;
+ c5 -= (t0 << 26);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 26;
+ c6 -= (t0 << 26);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 26;
+ c7 -= (t0 << 26);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 26;
+ c8 -= (t0 << 26);
+ c9 += t0;
+
+ r[0] = c0;
+ r[1] = c1;
+ r[2] = c2;
+ r[3] = c3;
+ r[4] = c4;
+ r[5] = c5;
+ r[6] = c6;
+ r[7] = c7;
+ r[8] = c8;
+ r[9] = c9;
+ }
+ @Override
+ protected void mult(long[] a, long[] b, long[] r) {
+ long c0 = (a[0] * b[0]);
+ long c1 = (a[0] * b[1]) + (a[1] * b[0]);
+ long c2 = (a[0] * b[2]) + (a[1] * b[1]) + (a[2] * b[0]);
+ long c3 = (a[0] * b[3]) + (a[1] * b[2]) + (a[2] * b[1]) + (a[3] * b[0]);
+ long c4 = (a[0] * b[4]) + (a[1] * b[3]) + (a[2] * b[2]) + (a[3] * b[1]) + (a[4] * b[0]);
+ long c5 = (a[0] * b[5]) + (a[1] * b[4]) + (a[2] * b[3]) + (a[3] * b[2]) + (a[4] * b[1]) + (a[5] * b[0]);
+ long c6 = (a[0] * b[6]) + (a[1] * b[5]) + (a[2] * b[4]) + (a[3] * b[3]) + (a[4] * b[2]) + (a[5] * b[1]) + (a[6] * b[0]);
+ long c7 = (a[0] * b[7]) + (a[1] * b[6]) + (a[2] * b[5]) + (a[3] * b[4]) + (a[4] * b[3]) + (a[5] * b[2]) + (a[6] * b[1]) + (a[7] * b[0]);
+ long c8 = (a[0] * b[8]) + (a[1] * b[7]) + (a[2] * b[6]) + (a[3] * b[5]) + (a[4] * b[4]) + (a[5] * b[3]) + (a[6] * b[2]) + (a[7] * b[1]) + (a[8] * b[0]);
+ long c9 = (a[0] * b[9]) + (a[1] * b[8]) + (a[2] * b[7]) + (a[3] * b[6]) + (a[4] * b[5]) + (a[5] * b[4]) + (a[6] * b[3]) + (a[7] * b[2]) + (a[8] * b[1]) + (a[9] * b[0]);
+ long c10 = (a[1] * b[9]) + (a[2] * b[8]) + (a[3] * b[7]) + (a[4] * b[6]) + (a[5] * b[5]) + (a[6] * b[4]) + (a[7] * b[3]) + (a[8] * b[2]) + (a[9] * b[1]);
+ long c11 = (a[2] * b[9]) + (a[3] * b[8]) + (a[4] * b[7]) + (a[5] * b[6]) + (a[6] * b[5]) + (a[7] * b[4]) + (a[8] * b[3]) + (a[9] * b[2]);
+ long c12 = (a[3] * b[9]) + (a[4] * b[8]) + (a[5] * b[7]) + (a[6] * b[6]) + (a[7] * b[5]) + (a[8] * b[4]) + (a[9] * b[3]);
+ long c13 = (a[4] * b[9]) + (a[5] * b[8]) + (a[6] * b[7]) + (a[7] * b[6]) + (a[8] * b[5]) + (a[9] * b[4]);
+ long c14 = (a[5] * b[9]) + (a[6] * b[8]) + (a[7] * b[7]) + (a[8] * b[6]) + (a[9] * b[5]);
+ long c15 = (a[6] * b[9]) + (a[7] * b[8]) + (a[8] * b[7]) + (a[9] * b[6]);
+ long c16 = (a[7] * b[9]) + (a[8] * b[8]) + (a[9] * b[7]);
+ long c17 = (a[8] * b[9]) + (a[9] * b[8]);
+ long c18 = (a[9] * b[9]);
+
+ carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18);
+ }
+ @Override
+ protected void reduce(long[] a) {
+ carryReduce(a, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9]);
+ }
+ @Override
+ protected void square(long[] a, long[] r) {
+ long c0 = (a[0] * a[0]);
+ long c1 = 2 * ((a[0] * a[1]));
+ long c2 = 2 * ((a[0] * a[2])) + (a[1] * a[1]);
+ long c3 = 2 * ((a[0] * a[3]) + (a[1] * a[2]));
+ long c4 = 2 * ((a[0] * a[4]) + (a[1] * a[3])) + (a[2] * a[2]);
+ long c5 = 2 * ((a[0] * a[5]) + (a[1] * a[4]) + (a[2] * a[3]));
+ long c6 = 2 * ((a[0] * a[6]) + (a[1] * a[5]) + (a[2] * a[4])) + (a[3] * a[3]);
+ long c7 = 2 * ((a[0] * a[7]) + (a[1] * a[6]) + (a[2] * a[5]) + (a[3] * a[4]));
+ long c8 = 2 * ((a[0] * a[8]) + (a[1] * a[7]) + (a[2] * a[6]) + (a[3] * a[5])) + (a[4] * a[4]);
+ long c9 = 2 * ((a[0] * a[9]) + (a[1] * a[8]) + (a[2] * a[7]) + (a[3] * a[6]) + (a[4] * a[5]));
+ long c10 = 2 * ((a[1] * a[9]) + (a[2] * a[8]) + (a[3] * a[7]) + (a[4] * a[6])) + (a[5] * a[5]);
+ long c11 = 2 * ((a[2] * a[9]) + (a[3] * a[8]) + (a[4] * a[7]) + (a[5] * a[6]));
+ long c12 = 2 * ((a[3] * a[9]) + (a[4] * a[8]) + (a[5] * a[7])) + (a[6] * a[6]);
+ long c13 = 2 * ((a[4] * a[9]) + (a[5] * a[8]) + (a[6] * a[7]));
+ long c14 = 2 * ((a[5] * a[9]) + (a[6] * a[8])) + (a[7] * a[7]);
+ long c15 = 2 * ((a[6] * a[9]) + (a[7] * a[8]));
+ long c16 = 2 * ((a[7] * a[9])) + (a[8] * a[8]);
+ long c17 = 2 * ((a[8] * a[9]));
+ long c18 = (a[9] * a[9]);
+
+ carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18);
+ }
+}
+
diff -r a659ccd1888d -r ddbd9744a3d5 src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomialP384.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomialP384.java Wed Dec 12 15:04:47 2018 +0530
@@ -0,0 +1,431 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is generated by FieldGen.jsh. Do not modify it directly.
+ */
+
+package sun.security.util.math.intpoly;
+
+import java.math.BigInteger;
+public class IntegerPolynomialP384 extends IntegerPolynomial {
+ private static final int BITS_PER_LIMB = 28;
+ private static final int NUM_LIMBS = 14;
+ private static final int MAX_ADDS = 2;
+ public static final BigInteger MODULUS = evaluateModulus();
+ private static final long CARRY_ADD = 1 << 27;
+ private static final int LIMB_MASK = -1 >>> (64 - BITS_PER_LIMB);
+ public IntegerPolynomialP384() {
+
+ super(BITS_PER_LIMB, NUM_LIMBS, MAX_ADDS, MODULUS);
+
+ }
+ private static BigInteger evaluateModulus() {
+ BigInteger result = BigInteger.valueOf(2).pow(384);
+ result = result.subtract(BigInteger.valueOf(2).pow(128));
+ result = result.subtract(BigInteger.valueOf(2).pow(96));
+ result = result.add(BigInteger.valueOf(2).pow(32));
+ result = result.subtract(BigInteger.valueOf(1));
+ return result;
+ }
+ @Override
+ protected void finalCarryReduceLast(long[] limbs) {
+ long c = limbs[13] >> 20;
+ limbs[13] -= c << 20;
+ limbs[4] += (c << 16) & LIMB_MASK;
+ limbs[5] += c >> 12;
+ limbs[3] += (c << 12) & LIMB_MASK;
+ limbs[4] += c >> 16;
+ limbs[1] -= (c << 4) & LIMB_MASK;
+ limbs[2] -= c >> 24;
+ limbs[0] += c;
+ }
+ private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26) {
+ long c27 = 0;
+ //reduce from position 26
+ c16 += (c26 << 24) & LIMB_MASK;
+ c17 += c26 >> 4;
+ c15 += (c26 << 20) & LIMB_MASK;
+ c16 += c26 >> 8;
+ c13 -= (c26 << 12) & LIMB_MASK;
+ c14 -= c26 >> 16;
+ c12 += (c26 << 8) & LIMB_MASK;
+ c13 += c26 >> 20;
+ //reduce from position 25
+ c15 += (c25 << 24) & LIMB_MASK;
+ c16 += c25 >> 4;
+ c14 += (c25 << 20) & LIMB_MASK;
+ c15 += c25 >> 8;
+ c12 -= (c25 << 12) & LIMB_MASK;
+ c13 -= c25 >> 16;
+ c11 += (c25 << 8) & LIMB_MASK;
+ c12 += c25 >> 20;
+ //reduce from position 24
+ c14 += (c24 << 24) & LIMB_MASK;
+ c15 += c24 >> 4;
+ c13 += (c24 << 20) & LIMB_MASK;
+ c14 += c24 >> 8;
+ c11 -= (c24 << 12) & LIMB_MASK;
+ c12 -= c24 >> 16;
+ c10 += (c24 << 8) & LIMB_MASK;
+ c11 += c24 >> 20;
+ //reduce from position 23
+ c13 += (c23 << 24) & LIMB_MASK;
+ c14 += c23 >> 4;
+ c12 += (c23 << 20) & LIMB_MASK;
+ c13 += c23 >> 8;
+ c10 -= (c23 << 12) & LIMB_MASK;
+ c11 -= c23 >> 16;
+ c9 += (c23 << 8) & LIMB_MASK;
+ c10 += c23 >> 20;
+ //reduce from position 22
+ c12 += (c22 << 24) & LIMB_MASK;
+ c13 += c22 >> 4;
+ c11 += (c22 << 20) & LIMB_MASK;
+ c12 += c22 >> 8;
+ c9 -= (c22 << 12) & LIMB_MASK;
+ c10 -= c22 >> 16;
+ c8 += (c22 << 8) & LIMB_MASK;
+ c9 += c22 >> 20;
+ //reduce from position 21
+ c11 += (c21 << 24) & LIMB_MASK;
+ c12 += c21 >> 4;
+ c10 += (c21 << 20) & LIMB_MASK;
+ c11 += c21 >> 8;
+ c8 -= (c21 << 12) & LIMB_MASK;
+ c9 -= c21 >> 16;
+ c7 += (c21 << 8) & LIMB_MASK;
+ c8 += c21 >> 20;
+ //reduce from position 20
+ c10 += (c20 << 24) & LIMB_MASK;
+ c11 += c20 >> 4;
+ c9 += (c20 << 20) & LIMB_MASK;
+ c10 += c20 >> 8;
+ c7 -= (c20 << 12) & LIMB_MASK;
+ c8 -= c20 >> 16;
+ c6 += (c20 << 8) & LIMB_MASK;
+ c7 += c20 >> 20;
+ //reduce from position 19
+ c9 += (c19 << 24) & LIMB_MASK;
+ c10 += c19 >> 4;
+ c8 += (c19 << 20) & LIMB_MASK;
+ c9 += c19 >> 8;
+ c6 -= (c19 << 12) & LIMB_MASK;
+ c7 -= c19 >> 16;
+ c5 += (c19 << 8) & LIMB_MASK;
+ c6 += c19 >> 20;
+ //reduce from position 18
+ c8 += (c18 << 24) & LIMB_MASK;
+ c9 += c18 >> 4;
+ c7 += (c18 << 20) & LIMB_MASK;
+ c8 += c18 >> 8;
+ c5 -= (c18 << 12) & LIMB_MASK;
+ c6 -= c18 >> 16;
+ c4 += (c18 << 8) & LIMB_MASK;
+ c5 += c18 >> 20;
+ //reduce from position 17
+ c7 += (c17 << 24) & LIMB_MASK;
+ c8 += c17 >> 4;
+ c6 += (c17 << 20) & LIMB_MASK;
+ c7 += c17 >> 8;
+ c4 -= (c17 << 12) & LIMB_MASK;
+ c5 -= c17 >> 16;
+ c3 += (c17 << 8) & LIMB_MASK;
+ c4 += c17 >> 20;
+ //reduce from position 16
+ c6 += (c16 << 24) & LIMB_MASK;
+ c7 += c16 >> 4;
+ c5 += (c16 << 20) & LIMB_MASK;
+ c6 += c16 >> 8;
+ c3 -= (c16 << 12) & LIMB_MASK;
+ c4 -= c16 >> 16;
+ c2 += (c16 << 8) & LIMB_MASK;
+ c3 += c16 >> 20;
+ //reduce from position 15
+ c5 += (c15 << 24) & LIMB_MASK;
+ c6 += c15 >> 4;
+ c4 += (c15 << 20) & LIMB_MASK;
+ c5 += c15 >> 8;
+ c2 -= (c15 << 12) & LIMB_MASK;
+ c3 -= c15 >> 16;
+ c1 += (c15 << 8) & LIMB_MASK;
+ c2 += c15 >> 20;
+ //reduce from position 14
+ c4 += (c14 << 24) & LIMB_MASK;
+ c5 += c14 >> 4;
+ c3 += (c14 << 20) & LIMB_MASK;
+ c4 += c14 >> 8;
+ c1 -= (c14 << 12) & LIMB_MASK;
+ c2 -= c14 >> 16;
+ c0 += (c14 << 8) & LIMB_MASK;
+ c1 += c14 >> 20;
+ c14 = 0;
+
+ carryReduce0(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27);
+ }
+ void carryReduce0(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27) {
+
+ //carry from position 12
+ long t0 = (c12 + CARRY_ADD) >> 28;
+ c12 -= (t0 << 28);
+ c13 += t0;
+ //carry from position 13
+ t0 = (c13 + CARRY_ADD) >> 28;
+ c13 -= (t0 << 28);
+ c14 += t0;
+ //reduce from position 14
+ c4 += (c14 << 24) & LIMB_MASK;
+ c5 += c14 >> 4;
+ c3 += (c14 << 20) & LIMB_MASK;
+ c4 += c14 >> 8;
+ c1 -= (c14 << 12) & LIMB_MASK;
+ c2 -= c14 >> 16;
+ c0 += (c14 << 8) & LIMB_MASK;
+ c1 += c14 >> 20;
+ //carry from position 0
+ t0 = (c0 + CARRY_ADD) >> 28;
+ c0 -= (t0 << 28);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 28;
+ c1 -= (t0 << 28);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 28;
+ c2 -= (t0 << 28);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 28;
+ c3 -= (t0 << 28);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 28;
+ c4 -= (t0 << 28);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 28;
+ c5 -= (t0 << 28);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 28;
+ c6 -= (t0 << 28);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 28;
+ c7 -= (t0 << 28);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 28;
+ c8 -= (t0 << 28);
+ c9 += t0;
+ //carry from position 9
+ t0 = (c9 + CARRY_ADD) >> 28;
+ c9 -= (t0 << 28);
+ c10 += t0;
+ //carry from position 10
+ t0 = (c10 + CARRY_ADD) >> 28;
+ c10 -= (t0 << 28);
+ c11 += t0;
+ //carry from position 11
+ t0 = (c11 + CARRY_ADD) >> 28;
+ c11 -= (t0 << 28);
+ c12 += t0;
+ //carry from position 12
+ t0 = (c12 + CARRY_ADD) >> 28;
+ c12 -= (t0 << 28);
+ c13 += t0;
+
+ r[0] = c0;
+ r[1] = c1;
+ r[2] = c2;
+ r[3] = c3;
+ r[4] = c4;
+ r[5] = c5;
+ r[6] = c6;
+ r[7] = c7;
+ r[8] = c8;
+ r[9] = c9;
+ r[10] = c10;
+ r[11] = c11;
+ r[12] = c12;
+ r[13] = c13;
+ }
+ private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13) {
+ long c14 = 0;
+ //carry from position 12
+ long t0 = (c12 + CARRY_ADD) >> 28;
+ c12 -= (t0 << 28);
+ c13 += t0;
+ //carry from position 13
+ t0 = (c13 + CARRY_ADD) >> 28;
+ c13 -= (t0 << 28);
+ c14 += t0;
+ //reduce from position 14
+ c4 += (c14 << 24) & LIMB_MASK;
+ c5 += c14 >> 4;
+ c3 += (c14 << 20) & LIMB_MASK;
+ c4 += c14 >> 8;
+ c1 -= (c14 << 12) & LIMB_MASK;
+ c2 -= c14 >> 16;
+ c0 += (c14 << 8) & LIMB_MASK;
+ c1 += c14 >> 20;
+ //carry from position 0
+ t0 = (c0 + CARRY_ADD) >> 28;
+ c0 -= (t0 << 28);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 28;
+ c1 -= (t0 << 28);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 28;
+ c2 -= (t0 << 28);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 28;
+ c3 -= (t0 << 28);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 28;
+ c4 -= (t0 << 28);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 28;
+ c5 -= (t0 << 28);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 28;
+ c6 -= (t0 << 28);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 28;
+ c7 -= (t0 << 28);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 28;
+ c8 -= (t0 << 28);
+ c9 += t0;
+ //carry from position 9
+ t0 = (c9 + CARRY_ADD) >> 28;
+ c9 -= (t0 << 28);
+ c10 += t0;
+ //carry from position 10
+ t0 = (c10 + CARRY_ADD) >> 28;
+ c10 -= (t0 << 28);
+ c11 += t0;
+ //carry from position 11
+ t0 = (c11 + CARRY_ADD) >> 28;
+ c11 -= (t0 << 28);
+ c12 += t0;
+ //carry from position 12
+ t0 = (c12 + CARRY_ADD) >> 28;
+ c12 -= (t0 << 28);
+ c13 += t0;
+
+ r[0] = c0;
+ r[1] = c1;
+ r[2] = c2;
+ r[3] = c3;
+ r[4] = c4;
+ r[5] = c5;
+ r[6] = c6;
+ r[7] = c7;
+ r[8] = c8;
+ r[9] = c9;
+ r[10] = c10;
+ r[11] = c11;
+ r[12] = c12;
+ r[13] = c13;
+ }
+ @Override
+ protected void mult(long[] a, long[] b, long[] r) {
+ long c0 = (a[0] * b[0]);
+ long c1 = (a[0] * b[1]) + (a[1] * b[0]);
+ long c2 = (a[0] * b[2]) + (a[1] * b[1]) + (a[2] * b[0]);
+ long c3 = (a[0] * b[3]) + (a[1] * b[2]) + (a[2] * b[1]) + (a[3] * b[0]);
+ long c4 = (a[0] * b[4]) + (a[1] * b[3]) + (a[2] * b[2]) + (a[3] * b[1]) + (a[4] * b[0]);
+ long c5 = (a[0] * b[5]) + (a[1] * b[4]) + (a[2] * b[3]) + (a[3] * b[2]) + (a[4] * b[1]) + (a[5] * b[0]);
+ long c6 = (a[0] * b[6]) + (a[1] * b[5]) + (a[2] * b[4]) + (a[3] * b[3]) + (a[4] * b[2]) + (a[5] * b[1]) + (a[6] * b[0]);
+ long c7 = (a[0] * b[7]) + (a[1] * b[6]) + (a[2] * b[5]) + (a[3] * b[4]) + (a[4] * b[3]) + (a[5] * b[2]) + (a[6] * b[1]) + (a[7] * b[0]);
+ long c8 = (a[0] * b[8]) + (a[1] * b[7]) + (a[2] * b[6]) + (a[3] * b[5]) + (a[4] * b[4]) + (a[5] * b[3]) + (a[6] * b[2]) + (a[7] * b[1]) + (a[8] * b[0]);
+ long c9 = (a[0] * b[9]) + (a[1] * b[8]) + (a[2] * b[7]) + (a[3] * b[6]) + (a[4] * b[5]) + (a[5] * b[4]) + (a[6] * b[3]) + (a[7] * b[2]) + (a[8] * b[1]) + (a[9] * b[0]);
+ long c10 = (a[0] * b[10]) + (a[1] * b[9]) + (a[2] * b[8]) + (a[3] * b[7]) + (a[4] * b[6]) + (a[5] * b[5]) + (a[6] * b[4]) + (a[7] * b[3]) + (a[8] * b[2]) + (a[9] * b[1]) + (a[10] * b[0]);
+ long c11 = (a[0] * b[11]) + (a[1] * b[10]) + (a[2] * b[9]) + (a[3] * b[8]) + (a[4] * b[7]) + (a[5] * b[6]) + (a[6] * b[5]) + (a[7] * b[4]) + (a[8] * b[3]) + (a[9] * b[2]) + (a[10] * b[1]) + (a[11] * b[0]);
+ long c12 = (a[0] * b[12]) + (a[1] * b[11]) + (a[2] * b[10]) + (a[3] * b[9]) + (a[4] * b[8]) + (a[5] * b[7]) + (a[6] * b[6]) + (a[7] * b[5]) + (a[8] * b[4]) + (a[9] * b[3]) + (a[10] * b[2]) + (a[11] * b[1]) + (a[12] * b[0]);
+ long c13 = (a[0] * b[13]) + (a[1] * b[12]) + (a[2] * b[11]) + (a[3] * b[10]) + (a[4] * b[9]) + (a[5] * b[8]) + (a[6] * b[7]) + (a[7] * b[6]) + (a[8] * b[5]) + (a[9] * b[4]) + (a[10] * b[3]) + (a[11] * b[2]) + (a[12] * b[1]) + (a[13] * b[0]);
+ long c14 = (a[1] * b[13]) + (a[2] * b[12]) + (a[3] * b[11]) + (a[4] * b[10]) + (a[5] * b[9]) + (a[6] * b[8]) + (a[7] * b[7]) + (a[8] * b[6]) + (a[9] * b[5]) + (a[10] * b[4]) + (a[11] * b[3]) + (a[12] * b[2]) + (a[13] * b[1]);
+ long c15 = (a[2] * b[13]) + (a[3] * b[12]) + (a[4] * b[11]) + (a[5] * b[10]) + (a[6] * b[9]) + (a[7] * b[8]) + (a[8] * b[7]) + (a[9] * b[6]) + (a[10] * b[5]) + (a[11] * b[4]) + (a[12] * b[3]) + (a[13] * b[2]);
+ long c16 = (a[3] * b[13]) + (a[4] * b[12]) + (a[5] * b[11]) + (a[6] * b[10]) + (a[7] * b[9]) + (a[8] * b[8]) + (a[9] * b[7]) + (a[10] * b[6]) + (a[11] * b[5]) + (a[12] * b[4]) + (a[13] * b[3]);
+ long c17 = (a[4] * b[13]) + (a[5] * b[12]) + (a[6] * b[11]) + (a[7] * b[10]) + (a[8] * b[9]) + (a[9] * b[8]) + (a[10] * b[7]) + (a[11] * b[6]) + (a[12] * b[5]) + (a[13] * b[4]);
+ long c18 = (a[5] * b[13]) + (a[6] * b[12]) + (a[7] * b[11]) + (a[8] * b[10]) + (a[9] * b[9]) + (a[10] * b[8]) + (a[11] * b[7]) + (a[12] * b[6]) + (a[13] * b[5]);
+ long c19 = (a[6] * b[13]) + (a[7] * b[12]) + (a[8] * b[11]) + (a[9] * b[10]) + (a[10] * b[9]) + (a[11] * b[8]) + (a[12] * b[7]) + (a[13] * b[6]);
+ long c20 = (a[7] * b[13]) + (a[8] * b[12]) + (a[9] * b[11]) + (a[10] * b[10]) + (a[11] * b[9]) + (a[12] * b[8]) + (a[13] * b[7]);
+ long c21 = (a[8] * b[13]) + (a[9] * b[12]) + (a[10] * b[11]) + (a[11] * b[10]) + (a[12] * b[9]) + (a[13] * b[8]);
+ long c22 = (a[9] * b[13]) + (a[10] * b[12]) + (a[11] * b[11]) + (a[12] * b[10]) + (a[13] * b[9]);
+ long c23 = (a[10] * b[13]) + (a[11] * b[12]) + (a[12] * b[11]) + (a[13] * b[10]);
+ long c24 = (a[11] * b[13]) + (a[12] * b[12]) + (a[13] * b[11]);
+ long c25 = (a[12] * b[13]) + (a[13] * b[12]);
+ long c26 = (a[13] * b[13]);
+
+ carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26);
+ }
+ @Override
+ protected void reduce(long[] a) {
+ carryReduce(a, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13]);
+ }
+ @Override
+ protected void square(long[] a, long[] r) {
+ long c0 = (a[0] * a[0]);
+ long c1 = 2 * ((a[0] * a[1]));
+ long c2 = 2 * ((a[0] * a[2])) + (a[1] * a[1]);
+ long c3 = 2 * ((a[0] * a[3]) + (a[1] * a[2]));
+ long c4 = 2 * ((a[0] * a[4]) + (a[1] * a[3])) + (a[2] * a[2]);
+ long c5 = 2 * ((a[0] * a[5]) + (a[1] * a[4]) + (a[2] * a[3]));
+ long c6 = 2 * ((a[0] * a[6]) + (a[1] * a[5]) + (a[2] * a[4])) + (a[3] * a[3]);
+ long c7 = 2 * ((a[0] * a[7]) + (a[1] * a[6]) + (a[2] * a[5]) + (a[3] * a[4]));
+ long c8 = 2 * ((a[0] * a[8]) + (a[1] * a[7]) + (a[2] * a[6]) + (a[3] * a[5])) + (a[4] * a[4]);
+ long c9 = 2 * ((a[0] * a[9]) + (a[1] * a[8]) + (a[2] * a[7]) + (a[3] * a[6]) + (a[4] * a[5]));
+ long c10 = 2 * ((a[0] * a[10]) + (a[1] * a[9]) + (a[2] * a[8]) + (a[3] * a[7]) + (a[4] * a[6])) + (a[5] * a[5]);
+ long c11 = 2 * ((a[0] * a[11]) + (a[1] * a[10]) + (a[2] * a[9]) + (a[3] * a[8]) + (a[4] * a[7]) + (a[5] * a[6]));
+ long c12 = 2 * ((a[0] * a[12]) + (a[1] * a[11]) + (a[2] * a[10]) + (a[3] * a[9]) + (a[4] * a[8]) + (a[5] * a[7])) + (a[6] * a[6]);
+ long c13 = 2 * ((a[0] * a[13]) + (a[1] * a[12]) + (a[2] * a[11]) + (a[3] * a[10]) + (a[4] * a[9]) + (a[5] * a[8]) + (a[6] * a[7]));
+ long c14 = 2 * ((a[1] * a[13]) + (a[2] * a[12]) + (a[3] * a[11]) + (a[4] * a[10]) + (a[5] * a[9]) + (a[6] * a[8])) + (a[7] * a[7]);
+ long c15 = 2 * ((a[2] * a[13]) + (a[3] * a[12]) + (a[4] * a[11]) + (a[5] * a[10]) + (a[6] * a[9]) + (a[7] * a[8]));
+ long c16 = 2 * ((a[3] * a[13]) + (a[4] * a[12]) + (a[5] * a[11]) + (a[6] * a[10]) + (a[7] * a[9])) + (a[8] * a[8]);
+ long c17 = 2 * ((a[4] * a[13]) + (a[5] * a[12]) + (a[6] * a[11]) + (a[7] * a[10]) + (a[8] * a[9]));
+ long c18 = 2 * ((a[5] * a[13]) + (a[6] * a[12]) + (a[7] * a[11]) + (a[8] * a[10])) + (a[9] * a[9]);
+ long c19 = 2 * ((a[6] * a[13]) + (a[7] * a[12]) + (a[8] * a[11]) + (a[9] * a[10]));
+ long c20 = 2 * ((a[7] * a[13]) + (a[8] * a[12]) + (a[9] * a[11])) + (a[10] * a[10]);
+ long c21 = 2 * ((a[8] * a[13]) + (a[9] * a[12]) + (a[10] * a[11]));
+ long c22 = 2 * ((a[9] * a[13]) + (a[10] * a[12])) + (a[11] * a[11]);
+ long c23 = 2 * ((a[10] * a[13]) + (a[11] * a[12]));
+ long c24 = 2 * ((a[11] * a[13])) + (a[12] * a[12]);
+ long c25 = 2 * ((a[12] * a[13]));
+ long c26 = (a[13] * a[13]);
+
+ carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26);
+ }
+}
+
diff -r a659ccd1888d -r ddbd9744a3d5 src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomialP521.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomialP521.java Wed Dec 12 15:04:47 2018 +0530
@@ -0,0 +1,417 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is generated by FieldGen.jsh. Do not modify it directly.
+ */
+
+package sun.security.util.math.intpoly;
+
+import java.math.BigInteger;
+public class IntegerPolynomialP521 extends IntegerPolynomial {
+ private static final int BITS_PER_LIMB = 28;
+ private static final int NUM_LIMBS = 19;
+ private static final int MAX_ADDS = 2;
+ public static final BigInteger MODULUS = evaluateModulus();
+ private static final long CARRY_ADD = 1 << 27;
+ private static final int LIMB_MASK = -1 >>> (64 - BITS_PER_LIMB);
+ public IntegerPolynomialP521() {
+
+ super(BITS_PER_LIMB, NUM_LIMBS, MAX_ADDS, MODULUS);
+
+ }
+ private static BigInteger evaluateModulus() {
+ BigInteger result = BigInteger.valueOf(2).pow(521);
+ result = result.subtract(BigInteger.valueOf(1));
+ return result;
+ }
+ @Override
+ protected void finalCarryReduceLast(long[] limbs) {
+ long c = limbs[18] >> 17;
+ limbs[18] -= c << 17;
+ limbs[0] += c;
+ }
+ private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27, long c28, long c29, long c30, long c31, long c32, long c33, long c34, long c35, long c36) {
+ long c37 = 0;
+ //reduce from position 36
+ c17 += (c36 << 11) & LIMB_MASK;
+ c18 += c36 >> 17;
+ //reduce from position 35
+ c16 += (c35 << 11) & LIMB_MASK;
+ c17 += c35 >> 17;
+ //reduce from position 34
+ c15 += (c34 << 11) & LIMB_MASK;
+ c16 += c34 >> 17;
+ //reduce from position 33
+ c14 += (c33 << 11) & LIMB_MASK;
+ c15 += c33 >> 17;
+ //reduce from position 32
+ c13 += (c32 << 11) & LIMB_MASK;
+ c14 += c32 >> 17;
+ //reduce from position 31
+ c12 += (c31 << 11) & LIMB_MASK;
+ c13 += c31 >> 17;
+ //reduce from position 30
+ c11 += (c30 << 11) & LIMB_MASK;
+ c12 += c30 >> 17;
+ //reduce from position 29
+ c10 += (c29 << 11) & LIMB_MASK;
+ c11 += c29 >> 17;
+ //reduce from position 28
+ c9 += (c28 << 11) & LIMB_MASK;
+ c10 += c28 >> 17;
+ //reduce from position 27
+ c8 += (c27 << 11) & LIMB_MASK;
+ c9 += c27 >> 17;
+ //reduce from position 26
+ c7 += (c26 << 11) & LIMB_MASK;
+ c8 += c26 >> 17;
+ //reduce from position 25
+ c6 += (c25 << 11) & LIMB_MASK;
+ c7 += c25 >> 17;
+ //reduce from position 24
+ c5 += (c24 << 11) & LIMB_MASK;
+ c6 += c24 >> 17;
+ //reduce from position 23
+ c4 += (c23 << 11) & LIMB_MASK;
+ c5 += c23 >> 17;
+ //reduce from position 22
+ c3 += (c22 << 11) & LIMB_MASK;
+ c4 += c22 >> 17;
+ //reduce from position 21
+ c2 += (c21 << 11) & LIMB_MASK;
+ c3 += c21 >> 17;
+ //reduce from position 20
+ c1 += (c20 << 11) & LIMB_MASK;
+ c2 += c20 >> 17;
+ //reduce from position 19
+ c0 += (c19 << 11) & LIMB_MASK;
+ c1 += c19 >> 17;
+ c19 = 0;
+
+ carryReduce0(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30, c31, c32, c33, c34, c35, c36, c37);
+ }
+ void carryReduce0(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27, long c28, long c29, long c30, long c31, long c32, long c33, long c34, long c35, long c36, long c37) {
+
+ //carry from position 17
+ long t0 = (c17 + CARRY_ADD) >> 28;
+ c17 -= (t0 << 28);
+ c18 += t0;
+ //carry from position 18
+ t0 = (c18 + CARRY_ADD) >> 28;
+ c18 -= (t0 << 28);
+ c19 += t0;
+ //reduce from position 19
+ c0 += (c19 << 11) & LIMB_MASK;
+ c1 += c19 >> 17;
+ //carry from position 0
+ t0 = (c0 + CARRY_ADD) >> 28;
+ c0 -= (t0 << 28);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 28;
+ c1 -= (t0 << 28);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 28;
+ c2 -= (t0 << 28);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 28;
+ c3 -= (t0 << 28);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 28;
+ c4 -= (t0 << 28);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 28;
+ c5 -= (t0 << 28);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 28;
+ c6 -= (t0 << 28);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 28;
+ c7 -= (t0 << 28);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 28;
+ c8 -= (t0 << 28);
+ c9 += t0;
+ //carry from position 9
+ t0 = (c9 + CARRY_ADD) >> 28;
+ c9 -= (t0 << 28);
+ c10 += t0;
+ //carry from position 10
+ t0 = (c10 + CARRY_ADD) >> 28;
+ c10 -= (t0 << 28);
+ c11 += t0;
+ //carry from position 11
+ t0 = (c11 + CARRY_ADD) >> 28;
+ c11 -= (t0 << 28);
+ c12 += t0;
+ //carry from position 12
+ t0 = (c12 + CARRY_ADD) >> 28;
+ c12 -= (t0 << 28);
+ c13 += t0;
+ //carry from position 13
+ t0 = (c13 + CARRY_ADD) >> 28;
+ c13 -= (t0 << 28);
+ c14 += t0;
+ //carry from position 14
+ t0 = (c14 + CARRY_ADD) >> 28;
+ c14 -= (t0 << 28);
+ c15 += t0;
+ //carry from position 15
+ t0 = (c15 + CARRY_ADD) >> 28;
+ c15 -= (t0 << 28);
+ c16 += t0;
+ //carry from position 16
+ t0 = (c16 + CARRY_ADD) >> 28;
+ c16 -= (t0 << 28);
+ c17 += t0;
+ //carry from position 17
+ t0 = (c17 + CARRY_ADD) >> 28;
+ c17 -= (t0 << 28);
+ c18 += t0;
+
+ r[0] = c0;
+ r[1] = c1;
+ r[2] = c2;
+ r[3] = c3;
+ r[4] = c4;
+ r[5] = c5;
+ r[6] = c6;
+ r[7] = c7;
+ r[8] = c8;
+ r[9] = c9;
+ r[10] = c10;
+ r[11] = c11;
+ r[12] = c12;
+ r[13] = c13;
+ r[14] = c14;
+ r[15] = c15;
+ r[16] = c16;
+ r[17] = c17;
+ r[18] = c18;
+ }
+ private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18) {
+ long c19 = 0;
+ //carry from position 17
+ long t0 = (c17 + CARRY_ADD) >> 28;
+ c17 -= (t0 << 28);
+ c18 += t0;
+ //carry from position 18
+ t0 = (c18 + CARRY_ADD) >> 28;
+ c18 -= (t0 << 28);
+ c19 += t0;
+ //reduce from position 19
+ c0 += (c19 << 11) & LIMB_MASK;
+ c1 += c19 >> 17;
+ //carry from position 0
+ t0 = (c0 + CARRY_ADD) >> 28;
+ c0 -= (t0 << 28);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 28;
+ c1 -= (t0 << 28);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 28;
+ c2 -= (t0 << 28);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 28;
+ c3 -= (t0 << 28);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 28;
+ c4 -= (t0 << 28);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 28;
+ c5 -= (t0 << 28);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 28;
+ c6 -= (t0 << 28);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 28;
+ c7 -= (t0 << 28);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 28;
+ c8 -= (t0 << 28);
+ c9 += t0;
+ //carry from position 9
+ t0 = (c9 + CARRY_ADD) >> 28;
+ c9 -= (t0 << 28);
+ c10 += t0;
+ //carry from position 10
+ t0 = (c10 + CARRY_ADD) >> 28;
+ c10 -= (t0 << 28);
+ c11 += t0;
+ //carry from position 11
+ t0 = (c11 + CARRY_ADD) >> 28;
+ c11 -= (t0 << 28);
+ c12 += t0;
+ //carry from position 12
+ t0 = (c12 + CARRY_ADD) >> 28;
+ c12 -= (t0 << 28);
+ c13 += t0;
+ //carry from position 13
+ t0 = (c13 + CARRY_ADD) >> 28;
+ c13 -= (t0 << 28);
+ c14 += t0;
+ //carry from position 14
+ t0 = (c14 + CARRY_ADD) >> 28;
+ c14 -= (t0 << 28);
+ c15 += t0;
+ //carry from position 15
+ t0 = (c15 + CARRY_ADD) >> 28;
+ c15 -= (t0 << 28);
+ c16 += t0;
+ //carry from position 16
+ t0 = (c16 + CARRY_ADD) >> 28;
+ c16 -= (t0 << 28);
+ c17 += t0;
+ //carry from position 17
+ t0 = (c17 + CARRY_ADD) >> 28;
+ c17 -= (t0 << 28);
+ c18 += t0;
+
+ r[0] = c0;
+ r[1] = c1;
+ r[2] = c2;
+ r[3] = c3;
+ r[4] = c4;
+ r[5] = c5;
+ r[6] = c6;
+ r[7] = c7;
+ r[8] = c8;
+ r[9] = c9;
+ r[10] = c10;
+ r[11] = c11;
+ r[12] = c12;
+ r[13] = c13;
+ r[14] = c14;
+ r[15] = c15;
+ r[16] = c16;
+ r[17] = c17;
+ r[18] = c18;
+ }
+ @Override
+ protected void mult(long[] a, long[] b, long[] r) {
+ long c0 = (a[0] * b[0]);
+ long c1 = (a[0] * b[1]) + (a[1] * b[0]);
+ long c2 = (a[0] * b[2]) + (a[1] * b[1]) + (a[2] * b[0]);
+ long c3 = (a[0] * b[3]) + (a[1] * b[2]) + (a[2] * b[1]) + (a[3] * b[0]);
+ long c4 = (a[0] * b[4]) + (a[1] * b[3]) + (a[2] * b[2]) + (a[3] * b[1]) + (a[4] * b[0]);
+ long c5 = (a[0] * b[5]) + (a[1] * b[4]) + (a[2] * b[3]) + (a[3] * b[2]) + (a[4] * b[1]) + (a[5] * b[0]);
+ long c6 = (a[0] * b[6]) + (a[1] * b[5]) + (a[2] * b[4]) + (a[3] * b[3]) + (a[4] * b[2]) + (a[5] * b[1]) + (a[6] * b[0]);
+ long c7 = (a[0] * b[7]) + (a[1] * b[6]) + (a[2] * b[5]) + (a[3] * b[4]) + (a[4] * b[3]) + (a[5] * b[2]) + (a[6] * b[1]) + (a[7] * b[0]);
+ long c8 = (a[0] * b[8]) + (a[1] * b[7]) + (a[2] * b[6]) + (a[3] * b[5]) + (a[4] * b[4]) + (a[5] * b[3]) + (a[6] * b[2]) + (a[7] * b[1]) + (a[8] * b[0]);
+ long c9 = (a[0] * b[9]) + (a[1] * b[8]) + (a[2] * b[7]) + (a[3] * b[6]) + (a[4] * b[5]) + (a[5] * b[4]) + (a[6] * b[3]) + (a[7] * b[2]) + (a[8] * b[1]) + (a[9] * b[0]);
+ long c10 = (a[0] * b[10]) + (a[1] * b[9]) + (a[2] * b[8]) + (a[3] * b[7]) + (a[4] * b[6]) + (a[5] * b[5]) + (a[6] * b[4]) + (a[7] * b[3]) + (a[8] * b[2]) + (a[9] * b[1]) + (a[10] * b[0]);
+ long c11 = (a[0] * b[11]) + (a[1] * b[10]) + (a[2] * b[9]) + (a[3] * b[8]) + (a[4] * b[7]) + (a[5] * b[6]) + (a[6] * b[5]) + (a[7] * b[4]) + (a[8] * b[3]) + (a[9] * b[2]) + (a[10] * b[1]) + (a[11] * b[0]);
+ long c12 = (a[0] * b[12]) + (a[1] * b[11]) + (a[2] * b[10]) + (a[3] * b[9]) + (a[4] * b[8]) + (a[5] * b[7]) + (a[6] * b[6]) + (a[7] * b[5]) + (a[8] * b[4]) + (a[9] * b[3]) + (a[10] * b[2]) + (a[11] * b[1]) + (a[12] * b[0]);
+ long c13 = (a[0] * b[13]) + (a[1] * b[12]) + (a[2] * b[11]) + (a[3] * b[10]) + (a[4] * b[9]) + (a[5] * b[8]) + (a[6] * b[7]) + (a[7] * b[6]) + (a[8] * b[5]) + (a[9] * b[4]) + (a[10] * b[3]) + (a[11] * b[2]) + (a[12] * b[1]) + (a[13] * b[0]);
+ long c14 = (a[0] * b[14]) + (a[1] * b[13]) + (a[2] * b[12]) + (a[3] * b[11]) + (a[4] * b[10]) + (a[5] * b[9]) + (a[6] * b[8]) + (a[7] * b[7]) + (a[8] * b[6]) + (a[9] * b[5]) + (a[10] * b[4]) + (a[11] * b[3]) + (a[12] * b[2]) + (a[13] * b[1]) + (a[14] * b[0]);
+ long c15 = (a[0] * b[15]) + (a[1] * b[14]) + (a[2] * b[13]) + (a[3] * b[12]) + (a[4] * b[11]) + (a[5] * b[10]) + (a[6] * b[9]) + (a[7] * b[8]) + (a[8] * b[7]) + (a[9] * b[6]) + (a[10] * b[5]) + (a[11] * b[4]) + (a[12] * b[3]) + (a[13] * b[2]) + (a[14] * b[1]) + (a[15] * b[0]);
+ long c16 = (a[0] * b[16]) + (a[1] * b[15]) + (a[2] * b[14]) + (a[3] * b[13]) + (a[4] * b[12]) + (a[5] * b[11]) + (a[6] * b[10]) + (a[7] * b[9]) + (a[8] * b[8]) + (a[9] * b[7]) + (a[10] * b[6]) + (a[11] * b[5]) + (a[12] * b[4]) + (a[13] * b[3]) + (a[14] * b[2]) + (a[15] * b[1]) + (a[16] * b[0]);
+ long c17 = (a[0] * b[17]) + (a[1] * b[16]) + (a[2] * b[15]) + (a[3] * b[14]) + (a[4] * b[13]) + (a[5] * b[12]) + (a[6] * b[11]) + (a[7] * b[10]) + (a[8] * b[9]) + (a[9] * b[8]) + (a[10] * b[7]) + (a[11] * b[6]) + (a[12] * b[5]) + (a[13] * b[4]) + (a[14] * b[3]) + (a[15] * b[2]) + (a[16] * b[1]) + (a[17] * b[0]);
+ long c18 = (a[0] * b[18]) + (a[1] * b[17]) + (a[2] * b[16]) + (a[3] * b[15]) + (a[4] * b[14]) + (a[5] * b[13]) + (a[6] * b[12]) + (a[7] * b[11]) + (a[8] * b[10]) + (a[9] * b[9]) + (a[10] * b[8]) + (a[11] * b[7]) + (a[12] * b[6]) + (a[13] * b[5]) + (a[14] * b[4]) + (a[15] * b[3]) + (a[16] * b[2]) + (a[17] * b[1]) + (a[18] * b[0]);
+ long c19 = (a[1] * b[18]) + (a[2] * b[17]) + (a[3] * b[16]) + (a[4] * b[15]) + (a[5] * b[14]) + (a[6] * b[13]) + (a[7] * b[12]) + (a[8] * b[11]) + (a[9] * b[10]) + (a[10] * b[9]) + (a[11] * b[8]) + (a[12] * b[7]) + (a[13] * b[6]) + (a[14] * b[5]) + (a[15] * b[4]) + (a[16] * b[3]) + (a[17] * b[2]) + (a[18] * b[1]);
+ long c20 = (a[2] * b[18]) + (a[3] * b[17]) + (a[4] * b[16]) + (a[5] * b[15]) + (a[6] * b[14]) + (a[7] * b[13]) + (a[8] * b[12]) + (a[9] * b[11]) + (a[10] * b[10]) + (a[11] * b[9]) + (a[12] * b[8]) + (a[13] * b[7]) + (a[14] * b[6]) + (a[15] * b[5]) + (a[16] * b[4]) + (a[17] * b[3]) + (a[18] * b[2]);
+ long c21 = (a[3] * b[18]) + (a[4] * b[17]) + (a[5] * b[16]) + (a[6] * b[15]) + (a[7] * b[14]) + (a[8] * b[13]) + (a[9] * b[12]) + (a[10] * b[11]) + (a[11] * b[10]) + (a[12] * b[9]) + (a[13] * b[8]) + (a[14] * b[7]) + (a[15] * b[6]) + (a[16] * b[5]) + (a[17] * b[4]) + (a[18] * b[3]);
+ long c22 = (a[4] * b[18]) + (a[5] * b[17]) + (a[6] * b[16]) + (a[7] * b[15]) + (a[8] * b[14]) + (a[9] * b[13]) + (a[10] * b[12]) + (a[11] * b[11]) + (a[12] * b[10]) + (a[13] * b[9]) + (a[14] * b[8]) + (a[15] * b[7]) + (a[16] * b[6]) + (a[17] * b[5]) + (a[18] * b[4]);
+ long c23 = (a[5] * b[18]) + (a[6] * b[17]) + (a[7] * b[16]) + (a[8] * b[15]) + (a[9] * b[14]) + (a[10] * b[13]) + (a[11] * b[12]) + (a[12] * b[11]) + (a[13] * b[10]) + (a[14] * b[9]) + (a[15] * b[8]) + (a[16] * b[7]) + (a[17] * b[6]) + (a[18] * b[5]);
+ long c24 = (a[6] * b[18]) + (a[7] * b[17]) + (a[8] * b[16]) + (a[9] * b[15]) + (a[10] * b[14]) + (a[11] * b[13]) + (a[12] * b[12]) + (a[13] * b[11]) + (a[14] * b[10]) + (a[15] * b[9]) + (a[16] * b[8]) + (a[17] * b[7]) + (a[18] * b[6]);
+ long c25 = (a[7] * b[18]) + (a[8] * b[17]) + (a[9] * b[16]) + (a[10] * b[15]) + (a[11] * b[14]) + (a[12] * b[13]) + (a[13] * b[12]) + (a[14] * b[11]) + (a[15] * b[10]) + (a[16] * b[9]) + (a[17] * b[8]) + (a[18] * b[7]);
+ long c26 = (a[8] * b[18]) + (a[9] * b[17]) + (a[10] * b[16]) + (a[11] * b[15]) + (a[12] * b[14]) + (a[13] * b[13]) + (a[14] * b[12]) + (a[15] * b[11]) + (a[16] * b[10]) + (a[17] * b[9]) + (a[18] * b[8]);
+ long c27 = (a[9] * b[18]) + (a[10] * b[17]) + (a[11] * b[16]) + (a[12] * b[15]) + (a[13] * b[14]) + (a[14] * b[13]) + (a[15] * b[12]) + (a[16] * b[11]) + (a[17] * b[10]) + (a[18] * b[9]);
+ long c28 = (a[10] * b[18]) + (a[11] * b[17]) + (a[12] * b[16]) + (a[13] * b[15]) + (a[14] * b[14]) + (a[15] * b[13]) + (a[16] * b[12]) + (a[17] * b[11]) + (a[18] * b[10]);
+ long c29 = (a[11] * b[18]) + (a[12] * b[17]) + (a[13] * b[16]) + (a[14] * b[15]) + (a[15] * b[14]) + (a[16] * b[13]) + (a[17] * b[12]) + (a[18] * b[11]);
+ long c30 = (a[12] * b[18]) + (a[13] * b[17]) + (a[14] * b[16]) + (a[15] * b[15]) + (a[16] * b[14]) + (a[17] * b[13]) + (a[18] * b[12]);
+ long c31 = (a[13] * b[18]) + (a[14] * b[17]) + (a[15] * b[16]) + (a[16] * b[15]) + (a[17] * b[14]) + (a[18] * b[13]);
+ long c32 = (a[14] * b[18]) + (a[15] * b[17]) + (a[16] * b[16]) + (a[17] * b[15]) + (a[18] * b[14]);
+ long c33 = (a[15] * b[18]) + (a[16] * b[17]) + (a[17] * b[16]) + (a[18] * b[15]);
+ long c34 = (a[16] * b[18]) + (a[17] * b[17]) + (a[18] * b[16]);
+ long c35 = (a[17] * b[18]) + (a[18] * b[17]);
+ long c36 = (a[18] * b[18]);
+
+ carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30, c31, c32, c33, c34, c35, c36);
+ }
+ @Override
+ protected void reduce(long[] a) {
+ carryReduce(a, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15], a[16], a[17], a[18]);
+ }
+ @Override
+ protected void square(long[] a, long[] r) {
+ long c0 = (a[0] * a[0]);
+ long c1 = 2 * ((a[0] * a[1]));
+ long c2 = 2 * ((a[0] * a[2])) + (a[1] * a[1]);
+ long c3 = 2 * ((a[0] * a[3]) + (a[1] * a[2]));
+ long c4 = 2 * ((a[0] * a[4]) + (a[1] * a[3])) + (a[2] * a[2]);
+ long c5 = 2 * ((a[0] * a[5]) + (a[1] * a[4]) + (a[2] * a[3]));
+ long c6 = 2 * ((a[0] * a[6]) + (a[1] * a[5]) + (a[2] * a[4])) + (a[3] * a[3]);
+ long c7 = 2 * ((a[0] * a[7]) + (a[1] * a[6]) + (a[2] * a[5]) + (a[3] * a[4]));
+ long c8 = 2 * ((a[0] * a[8]) + (a[1] * a[7]) + (a[2] * a[6]) + (a[3] * a[5])) + (a[4] * a[4]);
+ long c9 = 2 * ((a[0] * a[9]) + (a[1] * a[8]) + (a[2] * a[7]) + (a[3] * a[6]) + (a[4] * a[5]));
+ long c10 = 2 * ((a[0] * a[10]) + (a[1] * a[9]) + (a[2] * a[8]) + (a[3] * a[7]) + (a[4] * a[6])) + (a[5] * a[5]);
+ long c11 = 2 * ((a[0] * a[11]) + (a[1] * a[10]) + (a[2] * a[9]) + (a[3] * a[8]) + (a[4] * a[7]) + (a[5] * a[6]));
+ long c12 = 2 * ((a[0] * a[12]) + (a[1] * a[11]) + (a[2] * a[10]) + (a[3] * a[9]) + (a[4] * a[8]) + (a[5] * a[7])) + (a[6] * a[6]);
+ long c13 = 2 * ((a[0] * a[13]) + (a[1] * a[12]) + (a[2] * a[11]) + (a[3] * a[10]) + (a[4] * a[9]) + (a[5] * a[8]) + (a[6] * a[7]));
+ long c14 = 2 * ((a[0] * a[14]) + (a[1] * a[13]) + (a[2] * a[12]) + (a[3] * a[11]) + (a[4] * a[10]) + (a[5] * a[9]) + (a[6] * a[8])) + (a[7] * a[7]);
+ long c15 = 2 * ((a[0] * a[15]) + (a[1] * a[14]) + (a[2] * a[13]) + (a[3] * a[12]) + (a[4] * a[11]) + (a[5] * a[10]) + (a[6] * a[9]) + (a[7] * a[8]));
+ long c16 = 2 * ((a[0] * a[16]) + (a[1] * a[15]) + (a[2] * a[14]) + (a[3] * a[13]) + (a[4] * a[12]) + (a[5] * a[11]) + (a[6] * a[10]) + (a[7] * a[9])) + (a[8] * a[8]);
+ long c17 = 2 * ((a[0] * a[17]) + (a[1] * a[16]) + (a[2] * a[15]) + (a[3] * a[14]) + (a[4] * a[13]) + (a[5] * a[12]) + (a[6] * a[11]) + (a[7] * a[10]) + (a[8] * a[9]));
+ long c18 = 2 * ((a[0] * a[18]) + (a[1] * a[17]) + (a[2] * a[16]) + (a[3] * a[15]) + (a[4] * a[14]) + (a[5] * a[13]) + (a[6] * a[12]) + (a[7] * a[11]) + (a[8] * a[10])) + (a[9] * a[9]);
+ long c19 = 2 * ((a[1] * a[18]) + (a[2] * a[17]) + (a[3] * a[16]) + (a[4] * a[15]) + (a[5] * a[14]) + (a[6] * a[13]) + (a[7] * a[12]) + (a[8] * a[11]) + (a[9] * a[10]));
+ long c20 = 2 * ((a[2] * a[18]) + (a[3] * a[17]) + (a[4] * a[16]) + (a[5] * a[15]) + (a[6] * a[14]) + (a[7] * a[13]) + (a[8] * a[12]) + (a[9] * a[11])) + (a[10] * a[10]);
+ long c21 = 2 * ((a[3] * a[18]) + (a[4] * a[17]) + (a[5] * a[16]) + (a[6] * a[15]) + (a[7] * a[14]) + (a[8] * a[13]) + (a[9] * a[12]) + (a[10] * a[11]));
+ long c22 = 2 * ((a[4] * a[18]) + (a[5] * a[17]) + (a[6] * a[16]) + (a[7] * a[15]) + (a[8] * a[14]) + (a[9] * a[13]) + (a[10] * a[12])) + (a[11] * a[11]);
+ long c23 = 2 * ((a[5] * a[18]) + (a[6] * a[17]) + (a[7] * a[16]) + (a[8] * a[15]) + (a[9] * a[14]) + (a[10] * a[13]) + (a[11] * a[12]));
+ long c24 = 2 * ((a[6] * a[18]) + (a[7] * a[17]) + (a[8] * a[16]) + (a[9] * a[15]) + (a[10] * a[14]) + (a[11] * a[13])) + (a[12] * a[12]);
+ long c25 = 2 * ((a[7] * a[18]) + (a[8] * a[17]) + (a[9] * a[16]) + (a[10] * a[15]) + (a[11] * a[14]) + (a[12] * a[13]));
+ long c26 = 2 * ((a[8] * a[18]) + (a[9] * a[17]) + (a[10] * a[16]) + (a[11] * a[15]) + (a[12] * a[14])) + (a[13] * a[13]);
+ long c27 = 2 * ((a[9] * a[18]) + (a[10] * a[17]) + (a[11] * a[16]) + (a[12] * a[15]) + (a[13] * a[14]));
+ long c28 = 2 * ((a[10] * a[18]) + (a[11] * a[17]) + (a[12] * a[16]) + (a[13] * a[15])) + (a[14] * a[14]);
+ long c29 = 2 * ((a[11] * a[18]) + (a[12] * a[17]) + (a[13] * a[16]) + (a[14] * a[15]));
+ long c30 = 2 * ((a[12] * a[18]) + (a[13] * a[17]) + (a[14] * a[16])) + (a[15] * a[15]);
+ long c31 = 2 * ((a[13] * a[18]) + (a[14] * a[17]) + (a[15] * a[16]));
+ long c32 = 2 * ((a[14] * a[18]) + (a[15] * a[17])) + (a[16] * a[16]);
+ long c33 = 2 * ((a[15] * a[18]) + (a[16] * a[17]));
+ long c34 = 2 * ((a[16] * a[18])) + (a[17] * a[17]);
+ long c35 = 2 * ((a[17] * a[18]));
+ long c36 = (a[18] * a[18]);
+
+ carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30, c31, c32, c33, c34, c35, c36);
+ }
+}
+
diff -r a659ccd1888d -r ddbd9744a3d5 src/java.base/share/classes/sun/security/util/math/intpoly/P256OrderField.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/util/math/intpoly/P256OrderField.java Wed Dec 12 15:04:47 2018 +0530
@@ -0,0 +1,673 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is generated by FieldGen.jsh. Do not modify it directly.
+ */
+
+package sun.security.util.math.intpoly;
+
+import java.math.BigInteger;
+public class P256OrderField extends IntegerPolynomial {
+ private static final int BITS_PER_LIMB = 26;
+ private static final int NUM_LIMBS = 10;
+ private static final int MAX_ADDS = 1;
+ public static final BigInteger MODULUS = evaluateModulus();
+ private static final long CARRY_ADD = 1 << 25;
+ private static final int LIMB_MASK = -1 >>> (64 - BITS_PER_LIMB);
+ public P256OrderField() {
+
+ super(BITS_PER_LIMB, NUM_LIMBS, MAX_ADDS, MODULUS);
+
+ }
+ private static BigInteger evaluateModulus() {
+ BigInteger result = BigInteger.valueOf(2).pow(256);
+ result = result.add(BigInteger.valueOf(6497617));
+ result = result.subtract(BigInteger.valueOf(2).pow(26).multiply(BigInteger.valueOf(26038081)));
+ result = result.add(BigInteger.valueOf(2).pow(52).multiply(BigInteger.valueOf(32001852)));
+ result = result.subtract(BigInteger.valueOf(2).pow(78).multiply(BigInteger.valueOf(21586850)));
+ result = result.subtract(BigInteger.valueOf(2).pow(104).multiply(BigInteger.valueOf(4397317)));
+ result = result.add(BigInteger.valueOf(2).pow(182).multiply(BigInteger.valueOf(1024)));
+ result = result.subtract(BigInteger.valueOf(2).pow(208).multiply(BigInteger.valueOf(65536)));
+ return result;
+ }
+ @Override
+ protected void finalCarryReduceLast(long[] limbs) {
+ long c = limbs[9] >> 22;
+ limbs[9] -= c << 22;
+ long t0 = -6497617 * c;
+ limbs[0] += t0;
+ t0 = 26038081 * c;
+ limbs[1] += t0;
+ t0 = -32001852 * c;
+ limbs[2] += t0;
+ t0 = 21586850 * c;
+ limbs[3] += t0;
+ t0 = 4397317 * c;
+ limbs[4] += t0;
+ t0 = -1024 * c;
+ limbs[7] += t0;
+ t0 = 65536 * c;
+ limbs[8] += t0;
+ }
+ private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18) {
+ long c19 = 0;
+ //carry from position 0
+ long t0 = (c0 + CARRY_ADD) >> 26;
+ c0 -= (t0 << 26);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 26;
+ c1 -= (t0 << 26);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 26;
+ c2 -= (t0 << 26);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 26;
+ c3 -= (t0 << 26);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 26;
+ c4 -= (t0 << 26);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 26;
+ c5 -= (t0 << 26);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 26;
+ c6 -= (t0 << 26);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 26;
+ c7 -= (t0 << 26);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 26;
+ c8 -= (t0 << 26);
+ c9 += t0;
+ //carry from position 9
+ t0 = (c9 + CARRY_ADD) >> 26;
+ c9 -= (t0 << 26);
+ c10 += t0;
+ //carry from position 10
+ t0 = (c10 + CARRY_ADD) >> 26;
+ c10 -= (t0 << 26);
+ c11 += t0;
+ //carry from position 11
+ t0 = (c11 + CARRY_ADD) >> 26;
+ c11 -= (t0 << 26);
+ c12 += t0;
+ //carry from position 12
+ t0 = (c12 + CARRY_ADD) >> 26;
+ c12 -= (t0 << 26);
+ c13 += t0;
+ //carry from position 13
+ t0 = (c13 + CARRY_ADD) >> 26;
+ c13 -= (t0 << 26);
+ c14 += t0;
+ //carry from position 14
+ t0 = (c14 + CARRY_ADD) >> 26;
+ c14 -= (t0 << 26);
+ c15 += t0;
+ //carry from position 15
+ t0 = (c15 + CARRY_ADD) >> 26;
+ c15 -= (t0 << 26);
+ c16 += t0;
+ //carry from position 16
+ t0 = (c16 + CARRY_ADD) >> 26;
+ c16 -= (t0 << 26);
+ c17 += t0;
+ //carry from position 17
+ t0 = (c17 + CARRY_ADD) >> 26;
+ c17 -= (t0 << 26);
+ c18 += t0;
+ //carry from position 18
+ t0 = (c18 + CARRY_ADD) >> 26;
+ c18 -= (t0 << 26);
+ c19 += t0;
+
+ carryReduce0(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19);
+ }
+ void carryReduce0(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19) {
+ long t0;
+
+ //reduce from position 19
+ t0 = -6497617 * c19;
+ c9 += (t0 << 4) & LIMB_MASK;
+ c10 += t0 >> 22;
+ t0 = 26038081 * c19;
+ c10 += (t0 << 4) & LIMB_MASK;
+ c11 += t0 >> 22;
+ t0 = -32001852 * c19;
+ c11 += (t0 << 4) & LIMB_MASK;
+ c12 += t0 >> 22;
+ t0 = 21586850 * c19;
+ c12 += (t0 << 4) & LIMB_MASK;
+ c13 += t0 >> 22;
+ t0 = 4397317 * c19;
+ c13 += (t0 << 4) & LIMB_MASK;
+ c14 += t0 >> 22;
+ t0 = -1024 * c19;
+ c16 += (t0 << 4) & LIMB_MASK;
+ c17 += t0 >> 22;
+ t0 = 65536 * c19;
+ c17 += (t0 << 4) & LIMB_MASK;
+ c18 += t0 >> 22;
+ //reduce from position 18
+ t0 = -6497617 * c18;
+ c8 += (t0 << 4) & LIMB_MASK;
+ c9 += t0 >> 22;
+ t0 = 26038081 * c18;
+ c9 += (t0 << 4) & LIMB_MASK;
+ c10 += t0 >> 22;
+ t0 = -32001852 * c18;
+ c10 += (t0 << 4) & LIMB_MASK;
+ c11 += t0 >> 22;
+ t0 = 21586850 * c18;
+ c11 += (t0 << 4) & LIMB_MASK;
+ c12 += t0 >> 22;
+ t0 = 4397317 * c18;
+ c12 += (t0 << 4) & LIMB_MASK;
+ c13 += t0 >> 22;
+ t0 = -1024 * c18;
+ c15 += (t0 << 4) & LIMB_MASK;
+ c16 += t0 >> 22;
+ t0 = 65536 * c18;
+ c16 += (t0 << 4) & LIMB_MASK;
+ c17 += t0 >> 22;
+ //reduce from position 17
+ t0 = -6497617 * c17;
+ c7 += (t0 << 4) & LIMB_MASK;
+ c8 += t0 >> 22;
+ t0 = 26038081 * c17;
+ c8 += (t0 << 4) & LIMB_MASK;
+ c9 += t0 >> 22;
+ t0 = -32001852 * c17;
+ c9 += (t0 << 4) & LIMB_MASK;
+ c10 += t0 >> 22;
+ t0 = 21586850 * c17;
+ c10 += (t0 << 4) & LIMB_MASK;
+ c11 += t0 >> 22;
+ t0 = 4397317 * c17;
+ c11 += (t0 << 4) & LIMB_MASK;
+ c12 += t0 >> 22;
+ t0 = -1024 * c17;
+ c14 += (t0 << 4) & LIMB_MASK;
+ c15 += t0 >> 22;
+ t0 = 65536 * c17;
+ c15 += (t0 << 4) & LIMB_MASK;
+ c16 += t0 >> 22;
+ //reduce from position 16
+ t0 = -6497617 * c16;
+ c6 += (t0 << 4) & LIMB_MASK;
+ c7 += t0 >> 22;
+ t0 = 26038081 * c16;
+ c7 += (t0 << 4) & LIMB_MASK;
+ c8 += t0 >> 22;
+ t0 = -32001852 * c16;
+ c8 += (t0 << 4) & LIMB_MASK;
+ c9 += t0 >> 22;
+ t0 = 21586850 * c16;
+ c9 += (t0 << 4) & LIMB_MASK;
+ c10 += t0 >> 22;
+ t0 = 4397317 * c16;
+ c10 += (t0 << 4) & LIMB_MASK;
+ c11 += t0 >> 22;
+ t0 = -1024 * c16;
+ c13 += (t0 << 4) & LIMB_MASK;
+ c14 += t0 >> 22;
+ t0 = 65536 * c16;
+ c14 += (t0 << 4) & LIMB_MASK;
+ c15 += t0 >> 22;
+ //reduce from position 15
+ t0 = -6497617 * c15;
+ c5 += (t0 << 4) & LIMB_MASK;
+ c6 += t0 >> 22;
+ t0 = 26038081 * c15;
+ c6 += (t0 << 4) & LIMB_MASK;
+ c7 += t0 >> 22;
+ t0 = -32001852 * c15;
+ c7 += (t0 << 4) & LIMB_MASK;
+ c8 += t0 >> 22;
+ t0 = 21586850 * c15;
+ c8 += (t0 << 4) & LIMB_MASK;
+ c9 += t0 >> 22;
+ t0 = 4397317 * c15;
+ c9 += (t0 << 4) & LIMB_MASK;
+ c10 += t0 >> 22;
+ t0 = -1024 * c15;
+ c12 += (t0 << 4) & LIMB_MASK;
+ c13 += t0 >> 22;
+ t0 = 65536 * c15;
+ c13 += (t0 << 4) & LIMB_MASK;
+ c14 += t0 >> 22;
+ //reduce from position 14
+ t0 = -6497617 * c14;
+ c4 += (t0 << 4) & LIMB_MASK;
+ c5 += t0 >> 22;
+ t0 = 26038081 * c14;
+ c5 += (t0 << 4) & LIMB_MASK;
+ c6 += t0 >> 22;
+ t0 = -32001852 * c14;
+ c6 += (t0 << 4) & LIMB_MASK;
+ c7 += t0 >> 22;
+ t0 = 21586850 * c14;
+ c7 += (t0 << 4) & LIMB_MASK;
+ c8 += t0 >> 22;
+ t0 = 4397317 * c14;
+ c8 += (t0 << 4) & LIMB_MASK;
+ c9 += t0 >> 22;
+ t0 = -1024 * c14;
+ c11 += (t0 << 4) & LIMB_MASK;
+ c12 += t0 >> 22;
+ t0 = 65536 * c14;
+ c12 += (t0 << 4) & LIMB_MASK;
+ c13 += t0 >> 22;
+ //reduce from position 13
+ t0 = -6497617 * c13;
+ c3 += (t0 << 4) & LIMB_MASK;
+ c4 += t0 >> 22;
+ t0 = 26038081 * c13;
+ c4 += (t0 << 4) & LIMB_MASK;
+ c5 += t0 >> 22;
+ t0 = -32001852 * c13;
+ c5 += (t0 << 4) & LIMB_MASK;
+ c6 += t0 >> 22;
+ t0 = 21586850 * c13;
+ c6 += (t0 << 4) & LIMB_MASK;
+ c7 += t0 >> 22;
+ t0 = 4397317 * c13;
+ c7 += (t0 << 4) & LIMB_MASK;
+ c8 += t0 >> 22;
+ t0 = -1024 * c13;
+ c10 += (t0 << 4) & LIMB_MASK;
+ c11 += t0 >> 22;
+ t0 = 65536 * c13;
+ c11 += (t0 << 4) & LIMB_MASK;
+ c12 += t0 >> 22;
+ //reduce from position 12
+ t0 = -6497617 * c12;
+ c2 += (t0 << 4) & LIMB_MASK;
+ c3 += t0 >> 22;
+ t0 = 26038081 * c12;
+ c3 += (t0 << 4) & LIMB_MASK;
+ c4 += t0 >> 22;
+ t0 = -32001852 * c12;
+ c4 += (t0 << 4) & LIMB_MASK;
+ c5 += t0 >> 22;
+ t0 = 21586850 * c12;
+ c5 += (t0 << 4) & LIMB_MASK;
+ c6 += t0 >> 22;
+ t0 = 4397317 * c12;
+ c6 += (t0 << 4) & LIMB_MASK;
+ c7 += t0 >> 22;
+ t0 = -1024 * c12;
+ c9 += (t0 << 4) & LIMB_MASK;
+ c10 += t0 >> 22;
+ t0 = 65536 * c12;
+ c10 += (t0 << 4) & LIMB_MASK;
+ c11 += t0 >> 22;
+ //reduce from position 11
+ t0 = -6497617 * c11;
+ c1 += (t0 << 4) & LIMB_MASK;
+ c2 += t0 >> 22;
+ t0 = 26038081 * c11;
+ c2 += (t0 << 4) & LIMB_MASK;
+ c3 += t0 >> 22;
+ t0 = -32001852 * c11;
+ c3 += (t0 << 4) & LIMB_MASK;
+ c4 += t0 >> 22;
+ t0 = 21586850 * c11;
+ c4 += (t0 << 4) & LIMB_MASK;
+ c5 += t0 >> 22;
+ t0 = 4397317 * c11;
+ c5 += (t0 << 4) & LIMB_MASK;
+ c6 += t0 >> 22;
+ t0 = -1024 * c11;
+ c8 += (t0 << 4) & LIMB_MASK;
+ c9 += t0 >> 22;
+ t0 = 65536 * c11;
+ c9 += (t0 << 4) & LIMB_MASK;
+ c10 += t0 >> 22;
+ //reduce from position 10
+ t0 = -6497617 * c10;
+ c0 += (t0 << 4) & LIMB_MASK;
+ c1 += t0 >> 22;
+ t0 = 26038081 * c10;
+ c1 += (t0 << 4) & LIMB_MASK;
+ c2 += t0 >> 22;
+ t0 = -32001852 * c10;
+ c2 += (t0 << 4) & LIMB_MASK;
+ c3 += t0 >> 22;
+ t0 = 21586850 * c10;
+ c3 += (t0 << 4) & LIMB_MASK;
+ c4 += t0 >> 22;
+ t0 = 4397317 * c10;
+ c4 += (t0 << 4) & LIMB_MASK;
+ c5 += t0 >> 22;
+ t0 = -1024 * c10;
+ c7 += (t0 << 4) & LIMB_MASK;
+ c8 += t0 >> 22;
+ t0 = 65536 * c10;
+ c8 += (t0 << 4) & LIMB_MASK;
+ c9 += t0 >> 22;
+ c10 = 0;
+
+ carryReduce1(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19);
+ }
+ void carryReduce1(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19) {
+ long t0;
+
+ //carry from position 0
+ t0 = (c0 + CARRY_ADD) >> 26;
+ c0 -= (t0 << 26);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 26;
+ c1 -= (t0 << 26);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 26;
+ c2 -= (t0 << 26);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 26;
+ c3 -= (t0 << 26);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 26;
+ c4 -= (t0 << 26);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 26;
+ c5 -= (t0 << 26);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 26;
+ c6 -= (t0 << 26);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 26;
+ c7 -= (t0 << 26);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 26;
+ c8 -= (t0 << 26);
+ c9 += t0;
+ //carry from position 9
+ t0 = (c9 + CARRY_ADD) >> 26;
+ c9 -= (t0 << 26);
+ c10 += t0;
+
+ carryReduce2(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19);
+ }
+ void carryReduce2(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19) {
+ long t0;
+
+ //reduce from position 10
+ t0 = -6497617 * c10;
+ c0 += (t0 << 4) & LIMB_MASK;
+ c1 += t0 >> 22;
+ t0 = 26038081 * c10;
+ c1 += (t0 << 4) & LIMB_MASK;
+ c2 += t0 >> 22;
+ t0 = -32001852 * c10;
+ c2 += (t0 << 4) & LIMB_MASK;
+ c3 += t0 >> 22;
+ t0 = 21586850 * c10;
+ c3 += (t0 << 4) & LIMB_MASK;
+ c4 += t0 >> 22;
+ t0 = 4397317 * c10;
+ c4 += (t0 << 4) & LIMB_MASK;
+ c5 += t0 >> 22;
+ t0 = -1024 * c10;
+ c7 += (t0 << 4) & LIMB_MASK;
+ c8 += t0 >> 22;
+ t0 = 65536 * c10;
+ c8 += (t0 << 4) & LIMB_MASK;
+ c9 += t0 >> 22;
+ //carry from position 0
+ t0 = (c0 + CARRY_ADD) >> 26;
+ c0 -= (t0 << 26);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 26;
+ c1 -= (t0 << 26);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 26;
+ c2 -= (t0 << 26);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 26;
+ c3 -= (t0 << 26);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 26;
+ c4 -= (t0 << 26);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 26;
+ c5 -= (t0 << 26);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 26;
+ c6 -= (t0 << 26);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 26;
+ c7 -= (t0 << 26);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 26;
+ c8 -= (t0 << 26);
+ c9 += t0;
+
+ r[0] = c0;
+ r[1] = c1;
+ r[2] = c2;
+ r[3] = c3;
+ r[4] = c4;
+ r[5] = c5;
+ r[6] = c6;
+ r[7] = c7;
+ r[8] = c8;
+ r[9] = c9;
+ }
+ private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9) {
+ long c10 = 0;
+ //carry from position 0
+ long t0 = (c0 + CARRY_ADD) >> 26;
+ c0 -= (t0 << 26);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 26;
+ c1 -= (t0 << 26);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 26;
+ c2 -= (t0 << 26);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 26;
+ c3 -= (t0 << 26);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 26;
+ c4 -= (t0 << 26);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 26;
+ c5 -= (t0 << 26);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 26;
+ c6 -= (t0 << 26);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 26;
+ c7 -= (t0 << 26);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 26;
+ c8 -= (t0 << 26);
+ c9 += t0;
+ //carry from position 9
+ t0 = (c9 + CARRY_ADD) >> 26;
+ c9 -= (t0 << 26);
+ c10 += t0;
+
+ carryReduce0(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10);
+ }
+ void carryReduce0(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10) {
+ long t0;
+
+ //reduce from position 10
+ t0 = -6497617 * c10;
+ c0 += (t0 << 4) & LIMB_MASK;
+ c1 += t0 >> 22;
+ t0 = 26038081 * c10;
+ c1 += (t0 << 4) & LIMB_MASK;
+ c2 += t0 >> 22;
+ t0 = -32001852 * c10;
+ c2 += (t0 << 4) & LIMB_MASK;
+ c3 += t0 >> 22;
+ t0 = 21586850 * c10;
+ c3 += (t0 << 4) & LIMB_MASK;
+ c4 += t0 >> 22;
+ t0 = 4397317 * c10;
+ c4 += (t0 << 4) & LIMB_MASK;
+ c5 += t0 >> 22;
+ t0 = -1024 * c10;
+ c7 += (t0 << 4) & LIMB_MASK;
+ c8 += t0 >> 22;
+ t0 = 65536 * c10;
+ c8 += (t0 << 4) & LIMB_MASK;
+ c9 += t0 >> 22;
+ //carry from position 0
+ t0 = (c0 + CARRY_ADD) >> 26;
+ c0 -= (t0 << 26);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 26;
+ c1 -= (t0 << 26);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 26;
+ c2 -= (t0 << 26);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 26;
+ c3 -= (t0 << 26);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 26;
+ c4 -= (t0 << 26);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 26;
+ c5 -= (t0 << 26);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 26;
+ c6 -= (t0 << 26);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 26;
+ c7 -= (t0 << 26);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 26;
+ c8 -= (t0 << 26);
+ c9 += t0;
+
+ r[0] = c0;
+ r[1] = c1;
+ r[2] = c2;
+ r[3] = c3;
+ r[4] = c4;
+ r[5] = c5;
+ r[6] = c6;
+ r[7] = c7;
+ r[8] = c8;
+ r[9] = c9;
+ }
+ @Override
+ protected void mult(long[] a, long[] b, long[] r) {
+ long c0 = (a[0] * b[0]);
+ long c1 = (a[0] * b[1]) + (a[1] * b[0]);
+ long c2 = (a[0] * b[2]) + (a[1] * b[1]) + (a[2] * b[0]);
+ long c3 = (a[0] * b[3]) + (a[1] * b[2]) + (a[2] * b[1]) + (a[3] * b[0]);
+ long c4 = (a[0] * b[4]) + (a[1] * b[3]) + (a[2] * b[2]) + (a[3] * b[1]) + (a[4] * b[0]);
+ long c5 = (a[0] * b[5]) + (a[1] * b[4]) + (a[2] * b[3]) + (a[3] * b[2]) + (a[4] * b[1]) + (a[5] * b[0]);
+ long c6 = (a[0] * b[6]) + (a[1] * b[5]) + (a[2] * b[4]) + (a[3] * b[3]) + (a[4] * b[2]) + (a[5] * b[1]) + (a[6] * b[0]);
+ long c7 = (a[0] * b[7]) + (a[1] * b[6]) + (a[2] * b[5]) + (a[3] * b[4]) + (a[4] * b[3]) + (a[5] * b[2]) + (a[6] * b[1]) + (a[7] * b[0]);
+ long c8 = (a[0] * b[8]) + (a[1] * b[7]) + (a[2] * b[6]) + (a[3] * b[5]) + (a[4] * b[4]) + (a[5] * b[3]) + (a[6] * b[2]) + (a[7] * b[1]) + (a[8] * b[0]);
+ long c9 = (a[0] * b[9]) + (a[1] * b[8]) + (a[2] * b[7]) + (a[3] * b[6]) + (a[4] * b[5]) + (a[5] * b[4]) + (a[6] * b[3]) + (a[7] * b[2]) + (a[8] * b[1]) + (a[9] * b[0]);
+ long c10 = (a[1] * b[9]) + (a[2] * b[8]) + (a[3] * b[7]) + (a[4] * b[6]) + (a[5] * b[5]) + (a[6] * b[4]) + (a[7] * b[3]) + (a[8] * b[2]) + (a[9] * b[1]);
+ long c11 = (a[2] * b[9]) + (a[3] * b[8]) + (a[4] * b[7]) + (a[5] * b[6]) + (a[6] * b[5]) + (a[7] * b[4]) + (a[8] * b[3]) + (a[9] * b[2]);
+ long c12 = (a[3] * b[9]) + (a[4] * b[8]) + (a[5] * b[7]) + (a[6] * b[6]) + (a[7] * b[5]) + (a[8] * b[4]) + (a[9] * b[3]);
+ long c13 = (a[4] * b[9]) + (a[5] * b[8]) + (a[6] * b[7]) + (a[7] * b[6]) + (a[8] * b[5]) + (a[9] * b[4]);
+ long c14 = (a[5] * b[9]) + (a[6] * b[8]) + (a[7] * b[7]) + (a[8] * b[6]) + (a[9] * b[5]);
+ long c15 = (a[6] * b[9]) + (a[7] * b[8]) + (a[8] * b[7]) + (a[9] * b[6]);
+ long c16 = (a[7] * b[9]) + (a[8] * b[8]) + (a[9] * b[7]);
+ long c17 = (a[8] * b[9]) + (a[9] * b[8]);
+ long c18 = (a[9] * b[9]);
+
+ carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18);
+ }
+ @Override
+ protected void reduce(long[] a) {
+ carryReduce(a, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9]);
+ }
+ @Override
+ protected void square(long[] a, long[] r) {
+ long c0 = (a[0] * a[0]);
+ long c1 = 2 * ((a[0] * a[1]));
+ long c2 = 2 * ((a[0] * a[2])) + (a[1] * a[1]);
+ long c3 = 2 * ((a[0] * a[3]) + (a[1] * a[2]));
+ long c4 = 2 * ((a[0] * a[4]) + (a[1] * a[3])) + (a[2] * a[2]);
+ long c5 = 2 * ((a[0] * a[5]) + (a[1] * a[4]) + (a[2] * a[3]));
+ long c6 = 2 * ((a[0] * a[6]) + (a[1] * a[5]) + (a[2] * a[4])) + (a[3] * a[3]);
+ long c7 = 2 * ((a[0] * a[7]) + (a[1] * a[6]) + (a[2] * a[5]) + (a[3] * a[4]));
+ long c8 = 2 * ((a[0] * a[8]) + (a[1] * a[7]) + (a[2] * a[6]) + (a[3] * a[5])) + (a[4] * a[4]);
+ long c9 = 2 * ((a[0] * a[9]) + (a[1] * a[8]) + (a[2] * a[7]) + (a[3] * a[6]) + (a[4] * a[5]));
+ long c10 = 2 * ((a[1] * a[9]) + (a[2] * a[8]) + (a[3] * a[7]) + (a[4] * a[6])) + (a[5] * a[5]);
+ long c11 = 2 * ((a[2] * a[9]) + (a[3] * a[8]) + (a[4] * a[7]) + (a[5] * a[6]));
+ long c12 = 2 * ((a[3] * a[9]) + (a[4] * a[8]) + (a[5] * a[7])) + (a[6] * a[6]);
+ long c13 = 2 * ((a[4] * a[9]) + (a[5] * a[8]) + (a[6] * a[7]));
+ long c14 = 2 * ((a[5] * a[9]) + (a[6] * a[8])) + (a[7] * a[7]);
+ long c15 = 2 * ((a[6] * a[9]) + (a[7] * a[8]));
+ long c16 = 2 * ((a[7] * a[9])) + (a[8] * a[8]);
+ long c17 = 2 * ((a[8] * a[9]));
+ long c18 = (a[9] * a[9]);
+
+ carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18);
+ }
+}
+
diff -r a659ccd1888d -r ddbd9744a3d5 src/java.base/share/classes/sun/security/util/math/intpoly/P384OrderField.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/util/math/intpoly/P384OrderField.java Wed Dec 12 15:04:47 2018 +0530
@@ -0,0 +1,881 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is generated by FieldGen.jsh. Do not modify it directly.
+ */
+
+package sun.security.util.math.intpoly;
+
+import java.math.BigInteger;
+public class P384OrderField extends IntegerPolynomial {
+ private static final int BITS_PER_LIMB = 28;
+ private static final int NUM_LIMBS = 14;
+ private static final int MAX_ADDS = 1;
+ public static final BigInteger MODULUS = evaluateModulus();
+ private static final long CARRY_ADD = 1 << 27;
+ private static final int LIMB_MASK = -1 >>> (64 - BITS_PER_LIMB);
+ public P384OrderField() {
+
+ super(BITS_PER_LIMB, NUM_LIMBS, MAX_ADDS, MODULUS);
+
+ }
+ private static BigInteger evaluateModulus() {
+ BigInteger result = BigInteger.valueOf(2).pow(384);
+ result = result.subtract(BigInteger.valueOf(54187661));
+ result = result.subtract(BigInteger.valueOf(2).pow(28).multiply(BigInteger.valueOf(20867411)));
+ result = result.add(BigInteger.valueOf(2).pow(56).multiply(BigInteger.valueOf(10975981)));
+ result = result.add(BigInteger.valueOf(2).pow(84).multiply(BigInteger.valueOf(14361739)));
+ result = result.subtract(BigInteger.valueOf(2).pow(112).multiply(BigInteger.valueOf(35694566)));
+ result = result.subtract(BigInteger.valueOf(2).pow(140).multiply(BigInteger.valueOf(132168845)));
+ result = result.subtract(BigInteger.valueOf(2).pow(168).multiply(BigInteger.valueOf(3710130)));
+ return result;
+ }
+ @Override
+ protected void finalCarryReduceLast(long[] limbs) {
+ long c = limbs[13] >> 20;
+ limbs[13] -= c << 20;
+ long t0 = 54187661 * c;
+ limbs[0] += t0;
+ t0 = 20867411 * c;
+ limbs[1] += t0;
+ t0 = -10975981 * c;
+ limbs[2] += t0;
+ t0 = -14361739 * c;
+ limbs[3] += t0;
+ t0 = 35694566 * c;
+ limbs[4] += t0;
+ t0 = 132168845 * c;
+ limbs[5] += t0;
+ t0 = 3710130 * c;
+ limbs[6] += t0;
+ }
+ private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26) {
+ long c27 = 0;
+ //carry from position 0
+ long t0 = (c0 + CARRY_ADD) >> 28;
+ c0 -= (t0 << 28);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 28;
+ c1 -= (t0 << 28);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 28;
+ c2 -= (t0 << 28);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 28;
+ c3 -= (t0 << 28);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 28;
+ c4 -= (t0 << 28);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 28;
+ c5 -= (t0 << 28);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 28;
+ c6 -= (t0 << 28);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 28;
+ c7 -= (t0 << 28);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 28;
+ c8 -= (t0 << 28);
+ c9 += t0;
+ //carry from position 9
+ t0 = (c9 + CARRY_ADD) >> 28;
+ c9 -= (t0 << 28);
+ c10 += t0;
+ //carry from position 10
+ t0 = (c10 + CARRY_ADD) >> 28;
+ c10 -= (t0 << 28);
+ c11 += t0;
+ //carry from position 11
+ t0 = (c11 + CARRY_ADD) >> 28;
+ c11 -= (t0 << 28);
+ c12 += t0;
+ //carry from position 12
+ t0 = (c12 + CARRY_ADD) >> 28;
+ c12 -= (t0 << 28);
+ c13 += t0;
+ //carry from position 13
+ t0 = (c13 + CARRY_ADD) >> 28;
+ c13 -= (t0 << 28);
+ c14 += t0;
+ //carry from position 14
+ t0 = (c14 + CARRY_ADD) >> 28;
+ c14 -= (t0 << 28);
+ c15 += t0;
+ //carry from position 15
+ t0 = (c15 + CARRY_ADD) >> 28;
+ c15 -= (t0 << 28);
+ c16 += t0;
+ //carry from position 16
+ t0 = (c16 + CARRY_ADD) >> 28;
+ c16 -= (t0 << 28);
+ c17 += t0;
+ //carry from position 17
+ t0 = (c17 + CARRY_ADD) >> 28;
+ c17 -= (t0 << 28);
+ c18 += t0;
+ //carry from position 18
+ t0 = (c18 + CARRY_ADD) >> 28;
+ c18 -= (t0 << 28);
+ c19 += t0;
+ //carry from position 19
+ t0 = (c19 + CARRY_ADD) >> 28;
+ c19 -= (t0 << 28);
+ c20 += t0;
+ //carry from position 20
+ t0 = (c20 + CARRY_ADD) >> 28;
+ c20 -= (t0 << 28);
+ c21 += t0;
+ //carry from position 21
+ t0 = (c21 + CARRY_ADD) >> 28;
+ c21 -= (t0 << 28);
+ c22 += t0;
+ //carry from position 22
+ t0 = (c22 + CARRY_ADD) >> 28;
+ c22 -= (t0 << 28);
+ c23 += t0;
+ //carry from position 23
+ t0 = (c23 + CARRY_ADD) >> 28;
+ c23 -= (t0 << 28);
+ c24 += t0;
+ //carry from position 24
+ t0 = (c24 + CARRY_ADD) >> 28;
+ c24 -= (t0 << 28);
+ c25 += t0;
+ //carry from position 25
+ t0 = (c25 + CARRY_ADD) >> 28;
+ c25 -= (t0 << 28);
+ c26 += t0;
+ //carry from position 26
+ t0 = (c26 + CARRY_ADD) >> 28;
+ c26 -= (t0 << 28);
+ c27 += t0;
+
+ carryReduce0(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27);
+ }
+ void carryReduce0(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27) {
+ long t0;
+
+ //reduce from position 27
+ t0 = 54187661 * c27;
+ c13 += (t0 << 8) & LIMB_MASK;
+ c14 += t0 >> 20;
+ t0 = 20867411 * c27;
+ c14 += (t0 << 8) & LIMB_MASK;
+ c15 += t0 >> 20;
+ t0 = -10975981 * c27;
+ c15 += (t0 << 8) & LIMB_MASK;
+ c16 += t0 >> 20;
+ t0 = -14361739 * c27;
+ c16 += (t0 << 8) & LIMB_MASK;
+ c17 += t0 >> 20;
+ t0 = 35694566 * c27;
+ c17 += (t0 << 8) & LIMB_MASK;
+ c18 += t0 >> 20;
+ t0 = 132168845 * c27;
+ c18 += (t0 << 8) & LIMB_MASK;
+ c19 += t0 >> 20;
+ t0 = 3710130 * c27;
+ c19 += (t0 << 8) & LIMB_MASK;
+ c20 += t0 >> 20;
+ //reduce from position 26
+ t0 = 54187661 * c26;
+ c12 += (t0 << 8) & LIMB_MASK;
+ c13 += t0 >> 20;
+ t0 = 20867411 * c26;
+ c13 += (t0 << 8) & LIMB_MASK;
+ c14 += t0 >> 20;
+ t0 = -10975981 * c26;
+ c14 += (t0 << 8) & LIMB_MASK;
+ c15 += t0 >> 20;
+ t0 = -14361739 * c26;
+ c15 += (t0 << 8) & LIMB_MASK;
+ c16 += t0 >> 20;
+ t0 = 35694566 * c26;
+ c16 += (t0 << 8) & LIMB_MASK;
+ c17 += t0 >> 20;
+ t0 = 132168845 * c26;
+ c17 += (t0 << 8) & LIMB_MASK;
+ c18 += t0 >> 20;
+ t0 = 3710130 * c26;
+ c18 += (t0 << 8) & LIMB_MASK;
+ c19 += t0 >> 20;
+ //reduce from position 25
+ t0 = 54187661 * c25;
+ c11 += (t0 << 8) & LIMB_MASK;
+ c12 += t0 >> 20;
+ t0 = 20867411 * c25;
+ c12 += (t0 << 8) & LIMB_MASK;
+ c13 += t0 >> 20;
+ t0 = -10975981 * c25;
+ c13 += (t0 << 8) & LIMB_MASK;
+ c14 += t0 >> 20;
+ t0 = -14361739 * c25;
+ c14 += (t0 << 8) & LIMB_MASK;
+ c15 += t0 >> 20;
+ t0 = 35694566 * c25;
+ c15 += (t0 << 8) & LIMB_MASK;
+ c16 += t0 >> 20;
+ t0 = 132168845 * c25;
+ c16 += (t0 << 8) & LIMB_MASK;
+ c17 += t0 >> 20;
+ t0 = 3710130 * c25;
+ c17 += (t0 << 8) & LIMB_MASK;
+ c18 += t0 >> 20;
+ //reduce from position 24
+ t0 = 54187661 * c24;
+ c10 += (t0 << 8) & LIMB_MASK;
+ c11 += t0 >> 20;
+ t0 = 20867411 * c24;
+ c11 += (t0 << 8) & LIMB_MASK;
+ c12 += t0 >> 20;
+ t0 = -10975981 * c24;
+ c12 += (t0 << 8) & LIMB_MASK;
+ c13 += t0 >> 20;
+ t0 = -14361739 * c24;
+ c13 += (t0 << 8) & LIMB_MASK;
+ c14 += t0 >> 20;
+ t0 = 35694566 * c24;
+ c14 += (t0 << 8) & LIMB_MASK;
+ c15 += t0 >> 20;
+ t0 = 132168845 * c24;
+ c15 += (t0 << 8) & LIMB_MASK;
+ c16 += t0 >> 20;
+ t0 = 3710130 * c24;
+ c16 += (t0 << 8) & LIMB_MASK;
+ c17 += t0 >> 20;
+ //reduce from position 23
+ t0 = 54187661 * c23;
+ c9 += (t0 << 8) & LIMB_MASK;
+ c10 += t0 >> 20;
+ t0 = 20867411 * c23;
+ c10 += (t0 << 8) & LIMB_MASK;
+ c11 += t0 >> 20;
+ t0 = -10975981 * c23;
+ c11 += (t0 << 8) & LIMB_MASK;
+ c12 += t0 >> 20;
+ t0 = -14361739 * c23;
+ c12 += (t0 << 8) & LIMB_MASK;
+ c13 += t0 >> 20;
+ t0 = 35694566 * c23;
+ c13 += (t0 << 8) & LIMB_MASK;
+ c14 += t0 >> 20;
+ t0 = 132168845 * c23;
+ c14 += (t0 << 8) & LIMB_MASK;
+ c15 += t0 >> 20;
+ t0 = 3710130 * c23;
+ c15 += (t0 << 8) & LIMB_MASK;
+ c16 += t0 >> 20;
+ //reduce from position 22
+ t0 = 54187661 * c22;
+ c8 += (t0 << 8) & LIMB_MASK;
+ c9 += t0 >> 20;
+ t0 = 20867411 * c22;
+ c9 += (t0 << 8) & LIMB_MASK;
+ c10 += t0 >> 20;
+ t0 = -10975981 * c22;
+ c10 += (t0 << 8) & LIMB_MASK;
+ c11 += t0 >> 20;
+ t0 = -14361739 * c22;
+ c11 += (t0 << 8) & LIMB_MASK;
+ c12 += t0 >> 20;
+ t0 = 35694566 * c22;
+ c12 += (t0 << 8) & LIMB_MASK;
+ c13 += t0 >> 20;
+ t0 = 132168845 * c22;
+ c13 += (t0 << 8) & LIMB_MASK;
+ c14 += t0 >> 20;
+ t0 = 3710130 * c22;
+ c14 += (t0 << 8) & LIMB_MASK;
+ c15 += t0 >> 20;
+ //reduce from position 21
+ t0 = 54187661 * c21;
+ c7 += (t0 << 8) & LIMB_MASK;
+ c8 += t0 >> 20;
+ t0 = 20867411 * c21;
+ c8 += (t0 << 8) & LIMB_MASK;
+ c9 += t0 >> 20;
+ t0 = -10975981 * c21;
+ c9 += (t0 << 8) & LIMB_MASK;
+ c10 += t0 >> 20;
+ t0 = -14361739 * c21;
+ c10 += (t0 << 8) & LIMB_MASK;
+ c11 += t0 >> 20;
+ t0 = 35694566 * c21;
+ c11 += (t0 << 8) & LIMB_MASK;
+ c12 += t0 >> 20;
+ t0 = 132168845 * c21;
+ c12 += (t0 << 8) & LIMB_MASK;
+ c13 += t0 >> 20;
+ t0 = 3710130 * c21;
+ c13 += (t0 << 8) & LIMB_MASK;
+ c14 += t0 >> 20;
+ //reduce from position 20
+ t0 = 54187661 * c20;
+ c6 += (t0 << 8) & LIMB_MASK;
+ c7 += t0 >> 20;
+ t0 = 20867411 * c20;
+ c7 += (t0 << 8) & LIMB_MASK;
+ c8 += t0 >> 20;
+ t0 = -10975981 * c20;
+ c8 += (t0 << 8) & LIMB_MASK;
+ c9 += t0 >> 20;
+ t0 = -14361739 * c20;
+ c9 += (t0 << 8) & LIMB_MASK;
+ c10 += t0 >> 20;
+ t0 = 35694566 * c20;
+ c10 += (t0 << 8) & LIMB_MASK;
+ c11 += t0 >> 20;
+ t0 = 132168845 * c20;
+ c11 += (t0 << 8) & LIMB_MASK;
+ c12 += t0 >> 20;
+ t0 = 3710130 * c20;
+ c12 += (t0 << 8) & LIMB_MASK;
+ c13 += t0 >> 20;
+ //reduce from position 19
+ t0 = 54187661 * c19;
+ c5 += (t0 << 8) & LIMB_MASK;
+ c6 += t0 >> 20;
+ t0 = 20867411 * c19;
+ c6 += (t0 << 8) & LIMB_MASK;
+ c7 += t0 >> 20;
+ t0 = -10975981 * c19;
+ c7 += (t0 << 8) & LIMB_MASK;
+ c8 += t0 >> 20;
+ t0 = -14361739 * c19;
+ c8 += (t0 << 8) & LIMB_MASK;
+ c9 += t0 >> 20;
+ t0 = 35694566 * c19;
+ c9 += (t0 << 8) & LIMB_MASK;
+ c10 += t0 >> 20;
+ t0 = 132168845 * c19;
+ c10 += (t0 << 8) & LIMB_MASK;
+ c11 += t0 >> 20;
+ t0 = 3710130 * c19;
+ c11 += (t0 << 8) & LIMB_MASK;
+ c12 += t0 >> 20;
+ //reduce from position 18
+ t0 = 54187661 * c18;
+ c4 += (t0 << 8) & LIMB_MASK;
+ c5 += t0 >> 20;
+ t0 = 20867411 * c18;
+ c5 += (t0 << 8) & LIMB_MASK;
+ c6 += t0 >> 20;
+ t0 = -10975981 * c18;
+ c6 += (t0 << 8) & LIMB_MASK;
+ c7 += t0 >> 20;
+ t0 = -14361739 * c18;
+ c7 += (t0 << 8) & LIMB_MASK;
+ c8 += t0 >> 20;
+ t0 = 35694566 * c18;
+ c8 += (t0 << 8) & LIMB_MASK;
+ c9 += t0 >> 20;
+ t0 = 132168845 * c18;
+ c9 += (t0 << 8) & LIMB_MASK;
+ c10 += t0 >> 20;
+ t0 = 3710130 * c18;
+ c10 += (t0 << 8) & LIMB_MASK;
+ c11 += t0 >> 20;
+ //reduce from position 17
+ t0 = 54187661 * c17;
+ c3 += (t0 << 8) & LIMB_MASK;
+ c4 += t0 >> 20;
+ t0 = 20867411 * c17;
+ c4 += (t0 << 8) & LIMB_MASK;
+ c5 += t0 >> 20;
+ t0 = -10975981 * c17;
+ c5 += (t0 << 8) & LIMB_MASK;
+ c6 += t0 >> 20;
+ t0 = -14361739 * c17;
+ c6 += (t0 << 8) & LIMB_MASK;
+ c7 += t0 >> 20;
+ t0 = 35694566 * c17;
+ c7 += (t0 << 8) & LIMB_MASK;
+ c8 += t0 >> 20;
+ t0 = 132168845 * c17;
+ c8 += (t0 << 8) & LIMB_MASK;
+ c9 += t0 >> 20;
+ t0 = 3710130 * c17;
+ c9 += (t0 << 8) & LIMB_MASK;
+ c10 += t0 >> 20;
+ //reduce from position 16
+ t0 = 54187661 * c16;
+ c2 += (t0 << 8) & LIMB_MASK;
+ c3 += t0 >> 20;
+ t0 = 20867411 * c16;
+ c3 += (t0 << 8) & LIMB_MASK;
+ c4 += t0 >> 20;
+ t0 = -10975981 * c16;
+ c4 += (t0 << 8) & LIMB_MASK;
+ c5 += t0 >> 20;
+ t0 = -14361739 * c16;
+ c5 += (t0 << 8) & LIMB_MASK;
+ c6 += t0 >> 20;
+ t0 = 35694566 * c16;
+ c6 += (t0 << 8) & LIMB_MASK;
+ c7 += t0 >> 20;
+ t0 = 132168845 * c16;
+ c7 += (t0 << 8) & LIMB_MASK;
+ c8 += t0 >> 20;
+ t0 = 3710130 * c16;
+ c8 += (t0 << 8) & LIMB_MASK;
+ c9 += t0 >> 20;
+ //reduce from position 15
+ t0 = 54187661 * c15;
+ c1 += (t0 << 8) & LIMB_MASK;
+ c2 += t0 >> 20;
+ t0 = 20867411 * c15;
+ c2 += (t0 << 8) & LIMB_MASK;
+ c3 += t0 >> 20;
+ t0 = -10975981 * c15;
+ c3 += (t0 << 8) & LIMB_MASK;
+ c4 += t0 >> 20;
+ t0 = -14361739 * c15;
+ c4 += (t0 << 8) & LIMB_MASK;
+ c5 += t0 >> 20;
+ t0 = 35694566 * c15;
+ c5 += (t0 << 8) & LIMB_MASK;
+ c6 += t0 >> 20;
+ t0 = 132168845 * c15;
+ c6 += (t0 << 8) & LIMB_MASK;
+ c7 += t0 >> 20;
+ t0 = 3710130 * c15;
+ c7 += (t0 << 8) & LIMB_MASK;
+ c8 += t0 >> 20;
+ //reduce from position 14
+ t0 = 54187661 * c14;
+ c0 += (t0 << 8) & LIMB_MASK;
+ c1 += t0 >> 20;
+ t0 = 20867411 * c14;
+ c1 += (t0 << 8) & LIMB_MASK;
+ c2 += t0 >> 20;
+ t0 = -10975981 * c14;
+ c2 += (t0 << 8) & LIMB_MASK;
+ c3 += t0 >> 20;
+ t0 = -14361739 * c14;
+ c3 += (t0 << 8) & LIMB_MASK;
+ c4 += t0 >> 20;
+ t0 = 35694566 * c14;
+ c4 += (t0 << 8) & LIMB_MASK;
+ c5 += t0 >> 20;
+ t0 = 132168845 * c14;
+ c5 += (t0 << 8) & LIMB_MASK;
+ c6 += t0 >> 20;
+ t0 = 3710130 * c14;
+ c6 += (t0 << 8) & LIMB_MASK;
+ c7 += t0 >> 20;
+ c14 = 0;
+
+ carryReduce1(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27);
+ }
+ void carryReduce1(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27) {
+ long t0;
+
+ //carry from position 0
+ t0 = (c0 + CARRY_ADD) >> 28;
+ c0 -= (t0 << 28);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 28;
+ c1 -= (t0 << 28);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 28;
+ c2 -= (t0 << 28);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 28;
+ c3 -= (t0 << 28);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 28;
+ c4 -= (t0 << 28);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 28;
+ c5 -= (t0 << 28);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 28;
+ c6 -= (t0 << 28);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 28;
+ c7 -= (t0 << 28);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 28;
+ c8 -= (t0 << 28);
+ c9 += t0;
+ //carry from position 9
+ t0 = (c9 + CARRY_ADD) >> 28;
+ c9 -= (t0 << 28);
+ c10 += t0;
+ //carry from position 10
+ t0 = (c10 + CARRY_ADD) >> 28;
+ c10 -= (t0 << 28);
+ c11 += t0;
+ //carry from position 11
+ t0 = (c11 + CARRY_ADD) >> 28;
+ c11 -= (t0 << 28);
+ c12 += t0;
+ //carry from position 12
+ t0 = (c12 + CARRY_ADD) >> 28;
+ c12 -= (t0 << 28);
+ c13 += t0;
+ //carry from position 13
+ t0 = (c13 + CARRY_ADD) >> 28;
+ c13 -= (t0 << 28);
+ c14 += t0;
+
+ carryReduce2(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27);
+ }
+ void carryReduce2(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27) {
+ long t0;
+
+ //reduce from position 14
+ t0 = 54187661 * c14;
+ c0 += (t0 << 8) & LIMB_MASK;
+ c1 += t0 >> 20;
+ t0 = 20867411 * c14;
+ c1 += (t0 << 8) & LIMB_MASK;
+ c2 += t0 >> 20;
+ t0 = -10975981 * c14;
+ c2 += (t0 << 8) & LIMB_MASK;
+ c3 += t0 >> 20;
+ t0 = -14361739 * c14;
+ c3 += (t0 << 8) & LIMB_MASK;
+ c4 += t0 >> 20;
+ t0 = 35694566 * c14;
+ c4 += (t0 << 8) & LIMB_MASK;
+ c5 += t0 >> 20;
+ t0 = 132168845 * c14;
+ c5 += (t0 << 8) & LIMB_MASK;
+ c6 += t0 >> 20;
+ t0 = 3710130 * c14;
+ c6 += (t0 << 8) & LIMB_MASK;
+ c7 += t0 >> 20;
+ //carry from position 0
+ t0 = (c0 + CARRY_ADD) >> 28;
+ c0 -= (t0 << 28);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 28;
+ c1 -= (t0 << 28);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 28;
+ c2 -= (t0 << 28);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 28;
+ c3 -= (t0 << 28);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 28;
+ c4 -= (t0 << 28);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 28;
+ c5 -= (t0 << 28);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 28;
+ c6 -= (t0 << 28);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 28;
+ c7 -= (t0 << 28);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 28;
+ c8 -= (t0 << 28);
+ c9 += t0;
+ //carry from position 9
+ t0 = (c9 + CARRY_ADD) >> 28;
+ c9 -= (t0 << 28);
+ c10 += t0;
+ //carry from position 10
+ t0 = (c10 + CARRY_ADD) >> 28;
+ c10 -= (t0 << 28);
+ c11 += t0;
+ //carry from position 11
+ t0 = (c11 + CARRY_ADD) >> 28;
+ c11 -= (t0 << 28);
+ c12 += t0;
+ //carry from position 12
+ t0 = (c12 + CARRY_ADD) >> 28;
+ c12 -= (t0 << 28);
+ c13 += t0;
+
+ r[0] = c0;
+ r[1] = c1;
+ r[2] = c2;
+ r[3] = c3;
+ r[4] = c4;
+ r[5] = c5;
+ r[6] = c6;
+ r[7] = c7;
+ r[8] = c8;
+ r[9] = c9;
+ r[10] = c10;
+ r[11] = c11;
+ r[12] = c12;
+ r[13] = c13;
+ }
+ private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13) {
+ long c14 = 0;
+ //carry from position 0
+ long t0 = (c0 + CARRY_ADD) >> 28;
+ c0 -= (t0 << 28);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 28;
+ c1 -= (t0 << 28);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 28;
+ c2 -= (t0 << 28);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 28;
+ c3 -= (t0 << 28);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 28;
+ c4 -= (t0 << 28);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 28;
+ c5 -= (t0 << 28);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 28;
+ c6 -= (t0 << 28);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 28;
+ c7 -= (t0 << 28);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 28;
+ c8 -= (t0 << 28);
+ c9 += t0;
+ //carry from position 9
+ t0 = (c9 + CARRY_ADD) >> 28;
+ c9 -= (t0 << 28);
+ c10 += t0;
+ //carry from position 10
+ t0 = (c10 + CARRY_ADD) >> 28;
+ c10 -= (t0 << 28);
+ c11 += t0;
+ //carry from position 11
+ t0 = (c11 + CARRY_ADD) >> 28;
+ c11 -= (t0 << 28);
+ c12 += t0;
+ //carry from position 12
+ t0 = (c12 + CARRY_ADD) >> 28;
+ c12 -= (t0 << 28);
+ c13 += t0;
+ //carry from position 13
+ t0 = (c13 + CARRY_ADD) >> 28;
+ c13 -= (t0 << 28);
+ c14 += t0;
+
+ carryReduce0(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14);
+ }
+ void carryReduce0(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14) {
+ long t0;
+
+ //reduce from position 14
+ t0 = 54187661 * c14;
+ c0 += (t0 << 8) & LIMB_MASK;
+ c1 += t0 >> 20;
+ t0 = 20867411 * c14;
+ c1 += (t0 << 8) & LIMB_MASK;
+ c2 += t0 >> 20;
+ t0 = -10975981 * c14;
+ c2 += (t0 << 8) & LIMB_MASK;
+ c3 += t0 >> 20;
+ t0 = -14361739 * c14;
+ c3 += (t0 << 8) & LIMB_MASK;
+ c4 += t0 >> 20;
+ t0 = 35694566 * c14;
+ c4 += (t0 << 8) & LIMB_MASK;
+ c5 += t0 >> 20;
+ t0 = 132168845 * c14;
+ c5 += (t0 << 8) & LIMB_MASK;
+ c6 += t0 >> 20;
+ t0 = 3710130 * c14;
+ c6 += (t0 << 8) & LIMB_MASK;
+ c7 += t0 >> 20;
+ //carry from position 0
+ t0 = (c0 + CARRY_ADD) >> 28;
+ c0 -= (t0 << 28);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 28;
+ c1 -= (t0 << 28);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 28;
+ c2 -= (t0 << 28);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 28;
+ c3 -= (t0 << 28);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 28;
+ c4 -= (t0 << 28);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 28;
+ c5 -= (t0 << 28);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 28;
+ c6 -= (t0 << 28);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 28;
+ c7 -= (t0 << 28);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 28;
+ c8 -= (t0 << 28);
+ c9 += t0;
+ //carry from position 9
+ t0 = (c9 + CARRY_ADD) >> 28;
+ c9 -= (t0 << 28);
+ c10 += t0;
+ //carry from position 10
+ t0 = (c10 + CARRY_ADD) >> 28;
+ c10 -= (t0 << 28);
+ c11 += t0;
+ //carry from position 11
+ t0 = (c11 + CARRY_ADD) >> 28;
+ c11 -= (t0 << 28);
+ c12 += t0;
+ //carry from position 12
+ t0 = (c12 + CARRY_ADD) >> 28;
+ c12 -= (t0 << 28);
+ c13 += t0;
+
+ r[0] = c0;
+ r[1] = c1;
+ r[2] = c2;
+ r[3] = c3;
+ r[4] = c4;
+ r[5] = c5;
+ r[6] = c6;
+ r[7] = c7;
+ r[8] = c8;
+ r[9] = c9;
+ r[10] = c10;
+ r[11] = c11;
+ r[12] = c12;
+ r[13] = c13;
+ }
+ @Override
+ protected void mult(long[] a, long[] b, long[] r) {
+ long c0 = (a[0] * b[0]);
+ long c1 = (a[0] * b[1]) + (a[1] * b[0]);
+ long c2 = (a[0] * b[2]) + (a[1] * b[1]) + (a[2] * b[0]);
+ long c3 = (a[0] * b[3]) + (a[1] * b[2]) + (a[2] * b[1]) + (a[3] * b[0]);
+ long c4 = (a[0] * b[4]) + (a[1] * b[3]) + (a[2] * b[2]) + (a[3] * b[1]) + (a[4] * b[0]);
+ long c5 = (a[0] * b[5]) + (a[1] * b[4]) + (a[2] * b[3]) + (a[3] * b[2]) + (a[4] * b[1]) + (a[5] * b[0]);
+ long c6 = (a[0] * b[6]) + (a[1] * b[5]) + (a[2] * b[4]) + (a[3] * b[3]) + (a[4] * b[2]) + (a[5] * b[1]) + (a[6] * b[0]);
+ long c7 = (a[0] * b[7]) + (a[1] * b[6]) + (a[2] * b[5]) + (a[3] * b[4]) + (a[4] * b[3]) + (a[5] * b[2]) + (a[6] * b[1]) + (a[7] * b[0]);
+ long c8 = (a[0] * b[8]) + (a[1] * b[7]) + (a[2] * b[6]) + (a[3] * b[5]) + (a[4] * b[4]) + (a[5] * b[3]) + (a[6] * b[2]) + (a[7] * b[1]) + (a[8] * b[0]);
+ long c9 = (a[0] * b[9]) + (a[1] * b[8]) + (a[2] * b[7]) + (a[3] * b[6]) + (a[4] * b[5]) + (a[5] * b[4]) + (a[6] * b[3]) + (a[7] * b[2]) + (a[8] * b[1]) + (a[9] * b[0]);
+ long c10 = (a[0] * b[10]) + (a[1] * b[9]) + (a[2] * b[8]) + (a[3] * b[7]) + (a[4] * b[6]) + (a[5] * b[5]) + (a[6] * b[4]) + (a[7] * b[3]) + (a[8] * b[2]) + (a[9] * b[1]) + (a[10] * b[0]);
+ long c11 = (a[0] * b[11]) + (a[1] * b[10]) + (a[2] * b[9]) + (a[3] * b[8]) + (a[4] * b[7]) + (a[5] * b[6]) + (a[6] * b[5]) + (a[7] * b[4]) + (a[8] * b[3]) + (a[9] * b[2]) + (a[10] * b[1]) + (a[11] * b[0]);
+ long c12 = (a[0] * b[12]) + (a[1] * b[11]) + (a[2] * b[10]) + (a[3] * b[9]) + (a[4] * b[8]) + (a[5] * b[7]) + (a[6] * b[6]) + (a[7] * b[5]) + (a[8] * b[4]) + (a[9] * b[3]) + (a[10] * b[2]) + (a[11] * b[1]) + (a[12] * b[0]);
+ long c13 = (a[0] * b[13]) + (a[1] * b[12]) + (a[2] * b[11]) + (a[3] * b[10]) + (a[4] * b[9]) + (a[5] * b[8]) + (a[6] * b[7]) + (a[7] * b[6]) + (a[8] * b[5]) + (a[9] * b[4]) + (a[10] * b[3]) + (a[11] * b[2]) + (a[12] * b[1]) + (a[13] * b[0]);
+ long c14 = (a[1] * b[13]) + (a[2] * b[12]) + (a[3] * b[11]) + (a[4] * b[10]) + (a[5] * b[9]) + (a[6] * b[8]) + (a[7] * b[7]) + (a[8] * b[6]) + (a[9] * b[5]) + (a[10] * b[4]) + (a[11] * b[3]) + (a[12] * b[2]) + (a[13] * b[1]);
+ long c15 = (a[2] * b[13]) + (a[3] * b[12]) + (a[4] * b[11]) + (a[5] * b[10]) + (a[6] * b[9]) + (a[7] * b[8]) + (a[8] * b[7]) + (a[9] * b[6]) + (a[10] * b[5]) + (a[11] * b[4]) + (a[12] * b[3]) + (a[13] * b[2]);
+ long c16 = (a[3] * b[13]) + (a[4] * b[12]) + (a[5] * b[11]) + (a[6] * b[10]) + (a[7] * b[9]) + (a[8] * b[8]) + (a[9] * b[7]) + (a[10] * b[6]) + (a[11] * b[5]) + (a[12] * b[4]) + (a[13] * b[3]);
+ long c17 = (a[4] * b[13]) + (a[5] * b[12]) + (a[6] * b[11]) + (a[7] * b[10]) + (a[8] * b[9]) + (a[9] * b[8]) + (a[10] * b[7]) + (a[11] * b[6]) + (a[12] * b[5]) + (a[13] * b[4]);
+ long c18 = (a[5] * b[13]) + (a[6] * b[12]) + (a[7] * b[11]) + (a[8] * b[10]) + (a[9] * b[9]) + (a[10] * b[8]) + (a[11] * b[7]) + (a[12] * b[6]) + (a[13] * b[5]);
+ long c19 = (a[6] * b[13]) + (a[7] * b[12]) + (a[8] * b[11]) + (a[9] * b[10]) + (a[10] * b[9]) + (a[11] * b[8]) + (a[12] * b[7]) + (a[13] * b[6]);
+ long c20 = (a[7] * b[13]) + (a[8] * b[12]) + (a[9] * b[11]) + (a[10] * b[10]) + (a[11] * b[9]) + (a[12] * b[8]) + (a[13] * b[7]);
+ long c21 = (a[8] * b[13]) + (a[9] * b[12]) + (a[10] * b[11]) + (a[11] * b[10]) + (a[12] * b[9]) + (a[13] * b[8]);
+ long c22 = (a[9] * b[13]) + (a[10] * b[12]) + (a[11] * b[11]) + (a[12] * b[10]) + (a[13] * b[9]);
+ long c23 = (a[10] * b[13]) + (a[11] * b[12]) + (a[12] * b[11]) + (a[13] * b[10]);
+ long c24 = (a[11] * b[13]) + (a[12] * b[12]) + (a[13] * b[11]);
+ long c25 = (a[12] * b[13]) + (a[13] * b[12]);
+ long c26 = (a[13] * b[13]);
+
+ carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26);
+ }
+ @Override
+ protected void reduce(long[] a) {
+ carryReduce(a, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13]);
+ }
+ @Override
+ protected void square(long[] a, long[] r) {
+ long c0 = (a[0] * a[0]);
+ long c1 = 2 * ((a[0] * a[1]));
+ long c2 = 2 * ((a[0] * a[2])) + (a[1] * a[1]);
+ long c3 = 2 * ((a[0] * a[3]) + (a[1] * a[2]));
+ long c4 = 2 * ((a[0] * a[4]) + (a[1] * a[3])) + (a[2] * a[2]);
+ long c5 = 2 * ((a[0] * a[5]) + (a[1] * a[4]) + (a[2] * a[3]));
+ long c6 = 2 * ((a[0] * a[6]) + (a[1] * a[5]) + (a[2] * a[4])) + (a[3] * a[3]);
+ long c7 = 2 * ((a[0] * a[7]) + (a[1] * a[6]) + (a[2] * a[5]) + (a[3] * a[4]));
+ long c8 = 2 * ((a[0] * a[8]) + (a[1] * a[7]) + (a[2] * a[6]) + (a[3] * a[5])) + (a[4] * a[4]);
+ long c9 = 2 * ((a[0] * a[9]) + (a[1] * a[8]) + (a[2] * a[7]) + (a[3] * a[6]) + (a[4] * a[5]));
+ long c10 = 2 * ((a[0] * a[10]) + (a[1] * a[9]) + (a[2] * a[8]) + (a[3] * a[7]) + (a[4] * a[6])) + (a[5] * a[5]);
+ long c11 = 2 * ((a[0] * a[11]) + (a[1] * a[10]) + (a[2] * a[9]) + (a[3] * a[8]) + (a[4] * a[7]) + (a[5] * a[6]));
+ long c12 = 2 * ((a[0] * a[12]) + (a[1] * a[11]) + (a[2] * a[10]) + (a[3] * a[9]) + (a[4] * a[8]) + (a[5] * a[7])) + (a[6] * a[6]);
+ long c13 = 2 * ((a[0] * a[13]) + (a[1] * a[12]) + (a[2] * a[11]) + (a[3] * a[10]) + (a[4] * a[9]) + (a[5] * a[8]) + (a[6] * a[7]));
+ long c14 = 2 * ((a[1] * a[13]) + (a[2] * a[12]) + (a[3] * a[11]) + (a[4] * a[10]) + (a[5] * a[9]) + (a[6] * a[8])) + (a[7] * a[7]);
+ long c15 = 2 * ((a[2] * a[13]) + (a[3] * a[12]) + (a[4] * a[11]) + (a[5] * a[10]) + (a[6] * a[9]) + (a[7] * a[8]));
+ long c16 = 2 * ((a[3] * a[13]) + (a[4] * a[12]) + (a[5] * a[11]) + (a[6] * a[10]) + (a[7] * a[9])) + (a[8] * a[8]);
+ long c17 = 2 * ((a[4] * a[13]) + (a[5] * a[12]) + (a[6] * a[11]) + (a[7] * a[10]) + (a[8] * a[9]));
+ long c18 = 2 * ((a[5] * a[13]) + (a[6] * a[12]) + (a[7] * a[11]) + (a[8] * a[10])) + (a[9] * a[9]);
+ long c19 = 2 * ((a[6] * a[13]) + (a[7] * a[12]) + (a[8] * a[11]) + (a[9] * a[10]));
+ long c20 = 2 * ((a[7] * a[13]) + (a[8] * a[12]) + (a[9] * a[11])) + (a[10] * a[10]);
+ long c21 = 2 * ((a[8] * a[13]) + (a[9] * a[12]) + (a[10] * a[11]));
+ long c22 = 2 * ((a[9] * a[13]) + (a[10] * a[12])) + (a[11] * a[11]);
+ long c23 = 2 * ((a[10] * a[13]) + (a[11] * a[12]));
+ long c24 = 2 * ((a[11] * a[13])) + (a[12] * a[12]);
+ long c25 = 2 * ((a[12] * a[13]));
+ long c26 = (a[13] * a[13]);
+
+ carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26);
+ }
+}
+
diff -r a659ccd1888d -r ddbd9744a3d5 src/java.base/share/classes/sun/security/util/math/intpoly/P521OrderField.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/util/math/intpoly/P521OrderField.java Wed Dec 12 15:04:47 2018 +0530
@@ -0,0 +1,1377 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is generated by FieldGen.jsh. Do not modify it directly.
+ */
+
+package sun.security.util.math.intpoly;
+
+import java.math.BigInteger;
+public class P521OrderField extends IntegerPolynomial {
+ private static final int BITS_PER_LIMB = 28;
+ private static final int NUM_LIMBS = 19;
+ private static final int MAX_ADDS = 1;
+ public static final BigInteger MODULUS = evaluateModulus();
+ private static final long CARRY_ADD = 1 << 27;
+ private static final int LIMB_MASK = -1 >>> (64 - BITS_PER_LIMB);
+ public P521OrderField() {
+
+ super(BITS_PER_LIMB, NUM_LIMBS, MAX_ADDS, MODULUS);
+
+ }
+ private static BigInteger evaluateModulus() {
+ BigInteger result = BigInteger.valueOf(2).pow(521);
+ result = result.add(BigInteger.valueOf(20472841));
+ result = result.add(BigInteger.valueOf(2).pow(28).multiply(BigInteger.valueOf(117141993)));
+ result = result.subtract(BigInteger.valueOf(2).pow(56).multiply(BigInteger.valueOf(62411077)));
+ result = result.subtract(BigInteger.valueOf(2).pow(84).multiply(BigInteger.valueOf(56915814)));
+ result = result.add(BigInteger.valueOf(2).pow(112).multiply(BigInteger.valueOf(97532854)));
+ result = result.add(BigInteger.valueOf(2).pow(140).multiply(BigInteger.valueOf(76509338)));
+ result = result.subtract(BigInteger.valueOf(2).pow(168).multiply(BigInteger.valueOf(75510783)));
+ result = result.subtract(BigInteger.valueOf(2).pow(196).multiply(BigInteger.valueOf(67962521)));
+ result = result.add(BigInteger.valueOf(2).pow(224).multiply(BigInteger.valueOf(25593732)));
+ result = result.subtract(BigInteger.valueOf(2).pow(252).multiply(BigInteger.valueOf(91)));
+ return result;
+ }
+ @Override
+ protected void finalCarryReduceLast(long[] limbs) {
+ long c = limbs[18] >> 17;
+ limbs[18] -= c << 17;
+ long t0 = -20472841 * c;
+ limbs[0] += t0;
+ t0 = -117141993 * c;
+ limbs[1] += t0;
+ t0 = 62411077 * c;
+ limbs[2] += t0;
+ t0 = 56915814 * c;
+ limbs[3] += t0;
+ t0 = -97532854 * c;
+ limbs[4] += t0;
+ t0 = -76509338 * c;
+ limbs[5] += t0;
+ t0 = 75510783 * c;
+ limbs[6] += t0;
+ t0 = 67962521 * c;
+ limbs[7] += t0;
+ t0 = -25593732 * c;
+ limbs[8] += t0;
+ t0 = 91 * c;
+ limbs[9] += t0;
+ }
+ private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27, long c28, long c29, long c30, long c31, long c32, long c33, long c34, long c35, long c36) {
+ long c37 = 0;
+ //carry from position 0
+ long t0 = (c0 + CARRY_ADD) >> 28;
+ c0 -= (t0 << 28);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 28;
+ c1 -= (t0 << 28);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 28;
+ c2 -= (t0 << 28);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 28;
+ c3 -= (t0 << 28);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 28;
+ c4 -= (t0 << 28);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 28;
+ c5 -= (t0 << 28);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 28;
+ c6 -= (t0 << 28);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 28;
+ c7 -= (t0 << 28);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 28;
+ c8 -= (t0 << 28);
+ c9 += t0;
+ //carry from position 9
+ t0 = (c9 + CARRY_ADD) >> 28;
+ c9 -= (t0 << 28);
+ c10 += t0;
+ //carry from position 10
+ t0 = (c10 + CARRY_ADD) >> 28;
+ c10 -= (t0 << 28);
+ c11 += t0;
+ //carry from position 11
+ t0 = (c11 + CARRY_ADD) >> 28;
+ c11 -= (t0 << 28);
+ c12 += t0;
+ //carry from position 12
+ t0 = (c12 + CARRY_ADD) >> 28;
+ c12 -= (t0 << 28);
+ c13 += t0;
+ //carry from position 13
+ t0 = (c13 + CARRY_ADD) >> 28;
+ c13 -= (t0 << 28);
+ c14 += t0;
+ //carry from position 14
+ t0 = (c14 + CARRY_ADD) >> 28;
+ c14 -= (t0 << 28);
+ c15 += t0;
+ //carry from position 15
+ t0 = (c15 + CARRY_ADD) >> 28;
+ c15 -= (t0 << 28);
+ c16 += t0;
+ //carry from position 16
+ t0 = (c16 + CARRY_ADD) >> 28;
+ c16 -= (t0 << 28);
+ c17 += t0;
+ //carry from position 17
+ t0 = (c17 + CARRY_ADD) >> 28;
+ c17 -= (t0 << 28);
+ c18 += t0;
+ //carry from position 18
+ t0 = (c18 + CARRY_ADD) >> 28;
+ c18 -= (t0 << 28);
+ c19 += t0;
+ //carry from position 19
+ t0 = (c19 + CARRY_ADD) >> 28;
+ c19 -= (t0 << 28);
+ c20 += t0;
+ //carry from position 20
+ t0 = (c20 + CARRY_ADD) >> 28;
+ c20 -= (t0 << 28);
+ c21 += t0;
+ //carry from position 21
+ t0 = (c21 + CARRY_ADD) >> 28;
+ c21 -= (t0 << 28);
+ c22 += t0;
+ //carry from position 22
+ t0 = (c22 + CARRY_ADD) >> 28;
+ c22 -= (t0 << 28);
+ c23 += t0;
+ //carry from position 23
+ t0 = (c23 + CARRY_ADD) >> 28;
+ c23 -= (t0 << 28);
+ c24 += t0;
+ //carry from position 24
+ t0 = (c24 + CARRY_ADD) >> 28;
+ c24 -= (t0 << 28);
+ c25 += t0;
+ //carry from position 25
+ t0 = (c25 + CARRY_ADD) >> 28;
+ c25 -= (t0 << 28);
+ c26 += t0;
+ //carry from position 26
+ t0 = (c26 + CARRY_ADD) >> 28;
+ c26 -= (t0 << 28);
+ c27 += t0;
+ //carry from position 27
+ t0 = (c27 + CARRY_ADD) >> 28;
+ c27 -= (t0 << 28);
+ c28 += t0;
+ //carry from position 28
+ t0 = (c28 + CARRY_ADD) >> 28;
+ c28 -= (t0 << 28);
+ c29 += t0;
+ //carry from position 29
+ t0 = (c29 + CARRY_ADD) >> 28;
+ c29 -= (t0 << 28);
+ c30 += t0;
+ //carry from position 30
+ t0 = (c30 + CARRY_ADD) >> 28;
+ c30 -= (t0 << 28);
+ c31 += t0;
+ //carry from position 31
+ t0 = (c31 + CARRY_ADD) >> 28;
+ c31 -= (t0 << 28);
+ c32 += t0;
+ //carry from position 32
+ t0 = (c32 + CARRY_ADD) >> 28;
+ c32 -= (t0 << 28);
+ c33 += t0;
+ //carry from position 33
+ t0 = (c33 + CARRY_ADD) >> 28;
+ c33 -= (t0 << 28);
+ c34 += t0;
+ //carry from position 34
+ t0 = (c34 + CARRY_ADD) >> 28;
+ c34 -= (t0 << 28);
+ c35 += t0;
+ //carry from position 35
+ t0 = (c35 + CARRY_ADD) >> 28;
+ c35 -= (t0 << 28);
+ c36 += t0;
+ //carry from position 36
+ t0 = (c36 + CARRY_ADD) >> 28;
+ c36 -= (t0 << 28);
+ c37 += t0;
+
+ carryReduce0(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30, c31, c32, c33, c34, c35, c36, c37);
+ }
+ void carryReduce0(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27, long c28, long c29, long c30, long c31, long c32, long c33, long c34, long c35, long c36, long c37) {
+ long t0;
+
+ //reduce from position 37
+ t0 = -20472841 * c37;
+ c18 += (t0 << 11) & LIMB_MASK;
+ c19 += t0 >> 17;
+ t0 = -117141993 * c37;
+ c19 += (t0 << 11) & LIMB_MASK;
+ c20 += t0 >> 17;
+ t0 = 62411077 * c37;
+ c20 += (t0 << 11) & LIMB_MASK;
+ c21 += t0 >> 17;
+ t0 = 56915814 * c37;
+ c21 += (t0 << 11) & LIMB_MASK;
+ c22 += t0 >> 17;
+ t0 = -97532854 * c37;
+ c22 += (t0 << 11) & LIMB_MASK;
+ c23 += t0 >> 17;
+ t0 = -76509338 * c37;
+ c23 += (t0 << 11) & LIMB_MASK;
+ c24 += t0 >> 17;
+ t0 = 75510783 * c37;
+ c24 += (t0 << 11) & LIMB_MASK;
+ c25 += t0 >> 17;
+ t0 = 67962521 * c37;
+ c25 += (t0 << 11) & LIMB_MASK;
+ c26 += t0 >> 17;
+ t0 = -25593732 * c37;
+ c26 += (t0 << 11) & LIMB_MASK;
+ c27 += t0 >> 17;
+ t0 = 91 * c37;
+ c27 += (t0 << 11) & LIMB_MASK;
+ c28 += t0 >> 17;
+ //reduce from position 36
+ t0 = -20472841 * c36;
+ c17 += (t0 << 11) & LIMB_MASK;
+ c18 += t0 >> 17;
+ t0 = -117141993 * c36;
+ c18 += (t0 << 11) & LIMB_MASK;
+ c19 += t0 >> 17;
+ t0 = 62411077 * c36;
+ c19 += (t0 << 11) & LIMB_MASK;
+ c20 += t0 >> 17;
+ t0 = 56915814 * c36;
+ c20 += (t0 << 11) & LIMB_MASK;
+ c21 += t0 >> 17;
+ t0 = -97532854 * c36;
+ c21 += (t0 << 11) & LIMB_MASK;
+ c22 += t0 >> 17;
+ t0 = -76509338 * c36;
+ c22 += (t0 << 11) & LIMB_MASK;
+ c23 += t0 >> 17;
+ t0 = 75510783 * c36;
+ c23 += (t0 << 11) & LIMB_MASK;
+ c24 += t0 >> 17;
+ t0 = 67962521 * c36;
+ c24 += (t0 << 11) & LIMB_MASK;
+ c25 += t0 >> 17;
+ t0 = -25593732 * c36;
+ c25 += (t0 << 11) & LIMB_MASK;
+ c26 += t0 >> 17;
+ t0 = 91 * c36;
+ c26 += (t0 << 11) & LIMB_MASK;
+ c27 += t0 >> 17;
+ //reduce from position 35
+ t0 = -20472841 * c35;
+ c16 += (t0 << 11) & LIMB_MASK;
+ c17 += t0 >> 17;
+ t0 = -117141993 * c35;
+ c17 += (t0 << 11) & LIMB_MASK;
+ c18 += t0 >> 17;
+ t0 = 62411077 * c35;
+ c18 += (t0 << 11) & LIMB_MASK;
+ c19 += t0 >> 17;
+ t0 = 56915814 * c35;
+ c19 += (t0 << 11) & LIMB_MASK;
+ c20 += t0 >> 17;
+ t0 = -97532854 * c35;
+ c20 += (t0 << 11) & LIMB_MASK;
+ c21 += t0 >> 17;
+ t0 = -76509338 * c35;
+ c21 += (t0 << 11) & LIMB_MASK;
+ c22 += t0 >> 17;
+ t0 = 75510783 * c35;
+ c22 += (t0 << 11) & LIMB_MASK;
+ c23 += t0 >> 17;
+ t0 = 67962521 * c35;
+ c23 += (t0 << 11) & LIMB_MASK;
+ c24 += t0 >> 17;
+ t0 = -25593732 * c35;
+ c24 += (t0 << 11) & LIMB_MASK;
+ c25 += t0 >> 17;
+ t0 = 91 * c35;
+ c25 += (t0 << 11) & LIMB_MASK;
+ c26 += t0 >> 17;
+ //reduce from position 34
+ t0 = -20472841 * c34;
+ c15 += (t0 << 11) & LIMB_MASK;
+ c16 += t0 >> 17;
+ t0 = -117141993 * c34;
+ c16 += (t0 << 11) & LIMB_MASK;
+ c17 += t0 >> 17;
+ t0 = 62411077 * c34;
+ c17 += (t0 << 11) & LIMB_MASK;
+ c18 += t0 >> 17;
+ t0 = 56915814 * c34;
+ c18 += (t0 << 11) & LIMB_MASK;
+ c19 += t0 >> 17;
+ t0 = -97532854 * c34;
+ c19 += (t0 << 11) & LIMB_MASK;
+ c20 += t0 >> 17;
+ t0 = -76509338 * c34;
+ c20 += (t0 << 11) & LIMB_MASK;
+ c21 += t0 >> 17;
+ t0 = 75510783 * c34;
+ c21 += (t0 << 11) & LIMB_MASK;
+ c22 += t0 >> 17;
+ t0 = 67962521 * c34;
+ c22 += (t0 << 11) & LIMB_MASK;
+ c23 += t0 >> 17;
+ t0 = -25593732 * c34;
+ c23 += (t0 << 11) & LIMB_MASK;
+ c24 += t0 >> 17;
+ t0 = 91 * c34;
+ c24 += (t0 << 11) & LIMB_MASK;
+ c25 += t0 >> 17;
+ //reduce from position 33
+ t0 = -20472841 * c33;
+ c14 += (t0 << 11) & LIMB_MASK;
+ c15 += t0 >> 17;
+ t0 = -117141993 * c33;
+ c15 += (t0 << 11) & LIMB_MASK;
+ c16 += t0 >> 17;
+ t0 = 62411077 * c33;
+ c16 += (t0 << 11) & LIMB_MASK;
+ c17 += t0 >> 17;
+ t0 = 56915814 * c33;
+ c17 += (t0 << 11) & LIMB_MASK;
+ c18 += t0 >> 17;
+ t0 = -97532854 * c33;
+ c18 += (t0 << 11) & LIMB_MASK;
+ c19 += t0 >> 17;
+ t0 = -76509338 * c33;
+ c19 += (t0 << 11) & LIMB_MASK;
+ c20 += t0 >> 17;
+ t0 = 75510783 * c33;
+ c20 += (t0 << 11) & LIMB_MASK;
+ c21 += t0 >> 17;
+ t0 = 67962521 * c33;
+ c21 += (t0 << 11) & LIMB_MASK;
+ c22 += t0 >> 17;
+ t0 = -25593732 * c33;
+ c22 += (t0 << 11) & LIMB_MASK;
+ c23 += t0 >> 17;
+ t0 = 91 * c33;
+ c23 += (t0 << 11) & LIMB_MASK;
+ c24 += t0 >> 17;
+ //reduce from position 32
+ t0 = -20472841 * c32;
+ c13 += (t0 << 11) & LIMB_MASK;
+ c14 += t0 >> 17;
+ t0 = -117141993 * c32;
+ c14 += (t0 << 11) & LIMB_MASK;
+ c15 += t0 >> 17;
+ t0 = 62411077 * c32;
+ c15 += (t0 << 11) & LIMB_MASK;
+ c16 += t0 >> 17;
+ t0 = 56915814 * c32;
+ c16 += (t0 << 11) & LIMB_MASK;
+ c17 += t0 >> 17;
+ t0 = -97532854 * c32;
+ c17 += (t0 << 11) & LIMB_MASK;
+ c18 += t0 >> 17;
+ t0 = -76509338 * c32;
+ c18 += (t0 << 11) & LIMB_MASK;
+ c19 += t0 >> 17;
+ t0 = 75510783 * c32;
+ c19 += (t0 << 11) & LIMB_MASK;
+ c20 += t0 >> 17;
+ t0 = 67962521 * c32;
+ c20 += (t0 << 11) & LIMB_MASK;
+ c21 += t0 >> 17;
+ t0 = -25593732 * c32;
+ c21 += (t0 << 11) & LIMB_MASK;
+ c22 += t0 >> 17;
+ t0 = 91 * c32;
+ c22 += (t0 << 11) & LIMB_MASK;
+ c23 += t0 >> 17;
+ //reduce from position 31
+ t0 = -20472841 * c31;
+ c12 += (t0 << 11) & LIMB_MASK;
+ c13 += t0 >> 17;
+ t0 = -117141993 * c31;
+ c13 += (t0 << 11) & LIMB_MASK;
+ c14 += t0 >> 17;
+ t0 = 62411077 * c31;
+ c14 += (t0 << 11) & LIMB_MASK;
+ c15 += t0 >> 17;
+ t0 = 56915814 * c31;
+ c15 += (t0 << 11) & LIMB_MASK;
+ c16 += t0 >> 17;
+ t0 = -97532854 * c31;
+ c16 += (t0 << 11) & LIMB_MASK;
+ c17 += t0 >> 17;
+ t0 = -76509338 * c31;
+ c17 += (t0 << 11) & LIMB_MASK;
+ c18 += t0 >> 17;
+ t0 = 75510783 * c31;
+ c18 += (t0 << 11) & LIMB_MASK;
+ c19 += t0 >> 17;
+ t0 = 67962521 * c31;
+ c19 += (t0 << 11) & LIMB_MASK;
+ c20 += t0 >> 17;
+ t0 = -25593732 * c31;
+ c20 += (t0 << 11) & LIMB_MASK;
+ c21 += t0 >> 17;
+ t0 = 91 * c31;
+ c21 += (t0 << 11) & LIMB_MASK;
+ c22 += t0 >> 17;
+ //reduce from position 30
+ t0 = -20472841 * c30;
+ c11 += (t0 << 11) & LIMB_MASK;
+ c12 += t0 >> 17;
+ t0 = -117141993 * c30;
+ c12 += (t0 << 11) & LIMB_MASK;
+ c13 += t0 >> 17;
+ t0 = 62411077 * c30;
+ c13 += (t0 << 11) & LIMB_MASK;
+ c14 += t0 >> 17;
+ t0 = 56915814 * c30;
+ c14 += (t0 << 11) & LIMB_MASK;
+ c15 += t0 >> 17;
+ t0 = -97532854 * c30;
+ c15 += (t0 << 11) & LIMB_MASK;
+ c16 += t0 >> 17;
+ t0 = -76509338 * c30;
+ c16 += (t0 << 11) & LIMB_MASK;
+ c17 += t0 >> 17;
+ t0 = 75510783 * c30;
+ c17 += (t0 << 11) & LIMB_MASK;
+ c18 += t0 >> 17;
+ t0 = 67962521 * c30;
+ c18 += (t0 << 11) & LIMB_MASK;
+ c19 += t0 >> 17;
+ t0 = -25593732 * c30;
+ c19 += (t0 << 11) & LIMB_MASK;
+ c20 += t0 >> 17;
+ t0 = 91 * c30;
+ c20 += (t0 << 11) & LIMB_MASK;
+ c21 += t0 >> 17;
+ //reduce from position 29
+ t0 = -20472841 * c29;
+ c10 += (t0 << 11) & LIMB_MASK;
+ c11 += t0 >> 17;
+ t0 = -117141993 * c29;
+ c11 += (t0 << 11) & LIMB_MASK;
+ c12 += t0 >> 17;
+ t0 = 62411077 * c29;
+ c12 += (t0 << 11) & LIMB_MASK;
+ c13 += t0 >> 17;
+ t0 = 56915814 * c29;
+ c13 += (t0 << 11) & LIMB_MASK;
+ c14 += t0 >> 17;
+ t0 = -97532854 * c29;
+ c14 += (t0 << 11) & LIMB_MASK;
+ c15 += t0 >> 17;
+ t0 = -76509338 * c29;
+ c15 += (t0 << 11) & LIMB_MASK;
+ c16 += t0 >> 17;
+ t0 = 75510783 * c29;
+ c16 += (t0 << 11) & LIMB_MASK;
+ c17 += t0 >> 17;
+ t0 = 67962521 * c29;
+ c17 += (t0 << 11) & LIMB_MASK;
+ c18 += t0 >> 17;
+ t0 = -25593732 * c29;
+ c18 += (t0 << 11) & LIMB_MASK;
+ c19 += t0 >> 17;
+ t0 = 91 * c29;
+ c19 += (t0 << 11) & LIMB_MASK;
+ c20 += t0 >> 17;
+ //reduce from position 28
+ t0 = -20472841 * c28;
+ c9 += (t0 << 11) & LIMB_MASK;
+ c10 += t0 >> 17;
+ t0 = -117141993 * c28;
+ c10 += (t0 << 11) & LIMB_MASK;
+ c11 += t0 >> 17;
+ t0 = 62411077 * c28;
+ c11 += (t0 << 11) & LIMB_MASK;
+ c12 += t0 >> 17;
+ t0 = 56915814 * c28;
+ c12 += (t0 << 11) & LIMB_MASK;
+ c13 += t0 >> 17;
+ t0 = -97532854 * c28;
+ c13 += (t0 << 11) & LIMB_MASK;
+ c14 += t0 >> 17;
+ t0 = -76509338 * c28;
+ c14 += (t0 << 11) & LIMB_MASK;
+ c15 += t0 >> 17;
+ t0 = 75510783 * c28;
+ c15 += (t0 << 11) & LIMB_MASK;
+ c16 += t0 >> 17;
+ t0 = 67962521 * c28;
+ c16 += (t0 << 11) & LIMB_MASK;
+ c17 += t0 >> 17;
+ t0 = -25593732 * c28;
+ c17 += (t0 << 11) & LIMB_MASK;
+ c18 += t0 >> 17;
+ t0 = 91 * c28;
+ c18 += (t0 << 11) & LIMB_MASK;
+ c19 += t0 >> 17;
+
+ carryReduce1(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30, c31, c32, c33, c34, c35, c36, c37);
+ }
+ void carryReduce1(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27, long c28, long c29, long c30, long c31, long c32, long c33, long c34, long c35, long c36, long c37) {
+ long t0;
+
+ //carry from position 19
+ t0 = (c19 + CARRY_ADD) >> 28;
+ c19 -= (t0 << 28);
+ c20 += t0;
+ //carry from position 20
+ t0 = (c20 + CARRY_ADD) >> 28;
+ c20 -= (t0 << 28);
+ c21 += t0;
+ //carry from position 21
+ t0 = (c21 + CARRY_ADD) >> 28;
+ c21 -= (t0 << 28);
+ c22 += t0;
+ //carry from position 22
+ t0 = (c22 + CARRY_ADD) >> 28;
+ c22 -= (t0 << 28);
+ c23 += t0;
+ //carry from position 23
+ t0 = (c23 + CARRY_ADD) >> 28;
+ c23 -= (t0 << 28);
+ c24 += t0;
+ //carry from position 24
+ t0 = (c24 + CARRY_ADD) >> 28;
+ c24 -= (t0 << 28);
+ c25 += t0;
+ //carry from position 25
+ t0 = (c25 + CARRY_ADD) >> 28;
+ c25 -= (t0 << 28);
+ c26 += t0;
+ //carry from position 26
+ t0 = (c26 + CARRY_ADD) >> 28;
+ c26 -= (t0 << 28);
+ c27 += t0;
+ //reduce from position 27
+ t0 = -20472841 * c27;
+ c8 += (t0 << 11) & LIMB_MASK;
+ c9 += t0 >> 17;
+ t0 = -117141993 * c27;
+ c9 += (t0 << 11) & LIMB_MASK;
+ c10 += t0 >> 17;
+ t0 = 62411077 * c27;
+ c10 += (t0 << 11) & LIMB_MASK;
+ c11 += t0 >> 17;
+ t0 = 56915814 * c27;
+ c11 += (t0 << 11) & LIMB_MASK;
+ c12 += t0 >> 17;
+ t0 = -97532854 * c27;
+ c12 += (t0 << 11) & LIMB_MASK;
+ c13 += t0 >> 17;
+ t0 = -76509338 * c27;
+ c13 += (t0 << 11) & LIMB_MASK;
+ c14 += t0 >> 17;
+ t0 = 75510783 * c27;
+ c14 += (t0 << 11) & LIMB_MASK;
+ c15 += t0 >> 17;
+ t0 = 67962521 * c27;
+ c15 += (t0 << 11) & LIMB_MASK;
+ c16 += t0 >> 17;
+ t0 = -25593732 * c27;
+ c16 += (t0 << 11) & LIMB_MASK;
+ c17 += t0 >> 17;
+ t0 = 91 * c27;
+ c17 += (t0 << 11) & LIMB_MASK;
+ c18 += t0 >> 17;
+ //reduce from position 26
+ t0 = -20472841 * c26;
+ c7 += (t0 << 11) & LIMB_MASK;
+ c8 += t0 >> 17;
+ t0 = -117141993 * c26;
+ c8 += (t0 << 11) & LIMB_MASK;
+ c9 += t0 >> 17;
+ t0 = 62411077 * c26;
+ c9 += (t0 << 11) & LIMB_MASK;
+ c10 += t0 >> 17;
+ t0 = 56915814 * c26;
+ c10 += (t0 << 11) & LIMB_MASK;
+ c11 += t0 >> 17;
+ t0 = -97532854 * c26;
+ c11 += (t0 << 11) & LIMB_MASK;
+ c12 += t0 >> 17;
+ t0 = -76509338 * c26;
+ c12 += (t0 << 11) & LIMB_MASK;
+ c13 += t0 >> 17;
+ t0 = 75510783 * c26;
+ c13 += (t0 << 11) & LIMB_MASK;
+ c14 += t0 >> 17;
+ t0 = 67962521 * c26;
+ c14 += (t0 << 11) & LIMB_MASK;
+ c15 += t0 >> 17;
+ t0 = -25593732 * c26;
+ c15 += (t0 << 11) & LIMB_MASK;
+ c16 += t0 >> 17;
+ t0 = 91 * c26;
+ c16 += (t0 << 11) & LIMB_MASK;
+ c17 += t0 >> 17;
+ //reduce from position 25
+ t0 = -20472841 * c25;
+ c6 += (t0 << 11) & LIMB_MASK;
+ c7 += t0 >> 17;
+ t0 = -117141993 * c25;
+ c7 += (t0 << 11) & LIMB_MASK;
+ c8 += t0 >> 17;
+ t0 = 62411077 * c25;
+ c8 += (t0 << 11) & LIMB_MASK;
+ c9 += t0 >> 17;
+ t0 = 56915814 * c25;
+ c9 += (t0 << 11) & LIMB_MASK;
+ c10 += t0 >> 17;
+ t0 = -97532854 * c25;
+ c10 += (t0 << 11) & LIMB_MASK;
+ c11 += t0 >> 17;
+ t0 = -76509338 * c25;
+ c11 += (t0 << 11) & LIMB_MASK;
+ c12 += t0 >> 17;
+ t0 = 75510783 * c25;
+ c12 += (t0 << 11) & LIMB_MASK;
+ c13 += t0 >> 17;
+ t0 = 67962521 * c25;
+ c13 += (t0 << 11) & LIMB_MASK;
+ c14 += t0 >> 17;
+ t0 = -25593732 * c25;
+ c14 += (t0 << 11) & LIMB_MASK;
+ c15 += t0 >> 17;
+ t0 = 91 * c25;
+ c15 += (t0 << 11) & LIMB_MASK;
+ c16 += t0 >> 17;
+ //reduce from position 24
+ t0 = -20472841 * c24;
+ c5 += (t0 << 11) & LIMB_MASK;
+ c6 += t0 >> 17;
+ t0 = -117141993 * c24;
+ c6 += (t0 << 11) & LIMB_MASK;
+ c7 += t0 >> 17;
+ t0 = 62411077 * c24;
+ c7 += (t0 << 11) & LIMB_MASK;
+ c8 += t0 >> 17;
+ t0 = 56915814 * c24;
+ c8 += (t0 << 11) & LIMB_MASK;
+ c9 += t0 >> 17;
+ t0 = -97532854 * c24;
+ c9 += (t0 << 11) & LIMB_MASK;
+ c10 += t0 >> 17;
+ t0 = -76509338 * c24;
+ c10 += (t0 << 11) & LIMB_MASK;
+ c11 += t0 >> 17;
+ t0 = 75510783 * c24;
+ c11 += (t0 << 11) & LIMB_MASK;
+ c12 += t0 >> 17;
+ t0 = 67962521 * c24;
+ c12 += (t0 << 11) & LIMB_MASK;
+ c13 += t0 >> 17;
+ t0 = -25593732 * c24;
+ c13 += (t0 << 11) & LIMB_MASK;
+ c14 += t0 >> 17;
+ t0 = 91 * c24;
+ c14 += (t0 << 11) & LIMB_MASK;
+ c15 += t0 >> 17;
+ //reduce from position 23
+ t0 = -20472841 * c23;
+ c4 += (t0 << 11) & LIMB_MASK;
+ c5 += t0 >> 17;
+ t0 = -117141993 * c23;
+ c5 += (t0 << 11) & LIMB_MASK;
+ c6 += t0 >> 17;
+ t0 = 62411077 * c23;
+ c6 += (t0 << 11) & LIMB_MASK;
+ c7 += t0 >> 17;
+ t0 = 56915814 * c23;
+ c7 += (t0 << 11) & LIMB_MASK;
+ c8 += t0 >> 17;
+ t0 = -97532854 * c23;
+ c8 += (t0 << 11) & LIMB_MASK;
+ c9 += t0 >> 17;
+ t0 = -76509338 * c23;
+ c9 += (t0 << 11) & LIMB_MASK;
+ c10 += t0 >> 17;
+ t0 = 75510783 * c23;
+ c10 += (t0 << 11) & LIMB_MASK;
+ c11 += t0 >> 17;
+ t0 = 67962521 * c23;
+ c11 += (t0 << 11) & LIMB_MASK;
+ c12 += t0 >> 17;
+ t0 = -25593732 * c23;
+ c12 += (t0 << 11) & LIMB_MASK;
+ c13 += t0 >> 17;
+ t0 = 91 * c23;
+ c13 += (t0 << 11) & LIMB_MASK;
+ c14 += t0 >> 17;
+ //reduce from position 22
+ t0 = -20472841 * c22;
+ c3 += (t0 << 11) & LIMB_MASK;
+ c4 += t0 >> 17;
+ t0 = -117141993 * c22;
+ c4 += (t0 << 11) & LIMB_MASK;
+ c5 += t0 >> 17;
+ t0 = 62411077 * c22;
+ c5 += (t0 << 11) & LIMB_MASK;
+ c6 += t0 >> 17;
+ t0 = 56915814 * c22;
+ c6 += (t0 << 11) & LIMB_MASK;
+ c7 += t0 >> 17;
+ t0 = -97532854 * c22;
+ c7 += (t0 << 11) & LIMB_MASK;
+ c8 += t0 >> 17;
+ t0 = -76509338 * c22;
+ c8 += (t0 << 11) & LIMB_MASK;
+ c9 += t0 >> 17;
+ t0 = 75510783 * c22;
+ c9 += (t0 << 11) & LIMB_MASK;
+ c10 += t0 >> 17;
+ t0 = 67962521 * c22;
+ c10 += (t0 << 11) & LIMB_MASK;
+ c11 += t0 >> 17;
+ t0 = -25593732 * c22;
+ c11 += (t0 << 11) & LIMB_MASK;
+ c12 += t0 >> 17;
+ t0 = 91 * c22;
+ c12 += (t0 << 11) & LIMB_MASK;
+ c13 += t0 >> 17;
+ //reduce from position 21
+ t0 = -20472841 * c21;
+ c2 += (t0 << 11) & LIMB_MASK;
+ c3 += t0 >> 17;
+ t0 = -117141993 * c21;
+ c3 += (t0 << 11) & LIMB_MASK;
+ c4 += t0 >> 17;
+ t0 = 62411077 * c21;
+ c4 += (t0 << 11) & LIMB_MASK;
+ c5 += t0 >> 17;
+ t0 = 56915814 * c21;
+ c5 += (t0 << 11) & LIMB_MASK;
+ c6 += t0 >> 17;
+ t0 = -97532854 * c21;
+ c6 += (t0 << 11) & LIMB_MASK;
+ c7 += t0 >> 17;
+ t0 = -76509338 * c21;
+ c7 += (t0 << 11) & LIMB_MASK;
+ c8 += t0 >> 17;
+ t0 = 75510783 * c21;
+ c8 += (t0 << 11) & LIMB_MASK;
+ c9 += t0 >> 17;
+ t0 = 67962521 * c21;
+ c9 += (t0 << 11) & LIMB_MASK;
+ c10 += t0 >> 17;
+ t0 = -25593732 * c21;
+ c10 += (t0 << 11) & LIMB_MASK;
+ c11 += t0 >> 17;
+ t0 = 91 * c21;
+ c11 += (t0 << 11) & LIMB_MASK;
+ c12 += t0 >> 17;
+ //reduce from position 20
+ t0 = -20472841 * c20;
+ c1 += (t0 << 11) & LIMB_MASK;
+ c2 += t0 >> 17;
+ t0 = -117141993 * c20;
+ c2 += (t0 << 11) & LIMB_MASK;
+ c3 += t0 >> 17;
+ t0 = 62411077 * c20;
+ c3 += (t0 << 11) & LIMB_MASK;
+ c4 += t0 >> 17;
+ t0 = 56915814 * c20;
+ c4 += (t0 << 11) & LIMB_MASK;
+ c5 += t0 >> 17;
+ t0 = -97532854 * c20;
+ c5 += (t0 << 11) & LIMB_MASK;
+ c6 += t0 >> 17;
+ t0 = -76509338 * c20;
+ c6 += (t0 << 11) & LIMB_MASK;
+ c7 += t0 >> 17;
+ t0 = 75510783 * c20;
+ c7 += (t0 << 11) & LIMB_MASK;
+ c8 += t0 >> 17;
+ t0 = 67962521 * c20;
+ c8 += (t0 << 11) & LIMB_MASK;
+ c9 += t0 >> 17;
+ t0 = -25593732 * c20;
+ c9 += (t0 << 11) & LIMB_MASK;
+ c10 += t0 >> 17;
+ t0 = 91 * c20;
+ c10 += (t0 << 11) & LIMB_MASK;
+ c11 += t0 >> 17;
+ //reduce from position 19
+ t0 = -20472841 * c19;
+ c0 += (t0 << 11) & LIMB_MASK;
+ c1 += t0 >> 17;
+ t0 = -117141993 * c19;
+ c1 += (t0 << 11) & LIMB_MASK;
+ c2 += t0 >> 17;
+ t0 = 62411077 * c19;
+ c2 += (t0 << 11) & LIMB_MASK;
+ c3 += t0 >> 17;
+ t0 = 56915814 * c19;
+ c3 += (t0 << 11) & LIMB_MASK;
+ c4 += t0 >> 17;
+ t0 = -97532854 * c19;
+ c4 += (t0 << 11) & LIMB_MASK;
+ c5 += t0 >> 17;
+ t0 = -76509338 * c19;
+ c5 += (t0 << 11) & LIMB_MASK;
+ c6 += t0 >> 17;
+ t0 = 75510783 * c19;
+ c6 += (t0 << 11) & LIMB_MASK;
+ c7 += t0 >> 17;
+ t0 = 67962521 * c19;
+ c7 += (t0 << 11) & LIMB_MASK;
+ c8 += t0 >> 17;
+ t0 = -25593732 * c19;
+ c8 += (t0 << 11) & LIMB_MASK;
+ c9 += t0 >> 17;
+ t0 = 91 * c19;
+ c9 += (t0 << 11) & LIMB_MASK;
+ c10 += t0 >> 17;
+ c19 = 0;
+
+ carryReduce2(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30, c31, c32, c33, c34, c35, c36, c37);
+ }
+ void carryReduce2(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27, long c28, long c29, long c30, long c31, long c32, long c33, long c34, long c35, long c36, long c37) {
+ long t0;
+
+ //carry from position 0
+ t0 = (c0 + CARRY_ADD) >> 28;
+ c0 -= (t0 << 28);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 28;
+ c1 -= (t0 << 28);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 28;
+ c2 -= (t0 << 28);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 28;
+ c3 -= (t0 << 28);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 28;
+ c4 -= (t0 << 28);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 28;
+ c5 -= (t0 << 28);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 28;
+ c6 -= (t0 << 28);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 28;
+ c7 -= (t0 << 28);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 28;
+ c8 -= (t0 << 28);
+ c9 += t0;
+ //carry from position 9
+ t0 = (c9 + CARRY_ADD) >> 28;
+ c9 -= (t0 << 28);
+ c10 += t0;
+ //carry from position 10
+ t0 = (c10 + CARRY_ADD) >> 28;
+ c10 -= (t0 << 28);
+ c11 += t0;
+ //carry from position 11
+ t0 = (c11 + CARRY_ADD) >> 28;
+ c11 -= (t0 << 28);
+ c12 += t0;
+ //carry from position 12
+ t0 = (c12 + CARRY_ADD) >> 28;
+ c12 -= (t0 << 28);
+ c13 += t0;
+ //carry from position 13
+ t0 = (c13 + CARRY_ADD) >> 28;
+ c13 -= (t0 << 28);
+ c14 += t0;
+ //carry from position 14
+ t0 = (c14 + CARRY_ADD) >> 28;
+ c14 -= (t0 << 28);
+ c15 += t0;
+ //carry from position 15
+ t0 = (c15 + CARRY_ADD) >> 28;
+ c15 -= (t0 << 28);
+ c16 += t0;
+ //carry from position 16
+ t0 = (c16 + CARRY_ADD) >> 28;
+ c16 -= (t0 << 28);
+ c17 += t0;
+ //carry from position 17
+ t0 = (c17 + CARRY_ADD) >> 28;
+ c17 -= (t0 << 28);
+ c18 += t0;
+ //carry from position 18
+ t0 = (c18 + CARRY_ADD) >> 28;
+ c18 -= (t0 << 28);
+ c19 += t0;
+
+ carryReduce3(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30, c31, c32, c33, c34, c35, c36, c37);
+ }
+ void carryReduce3(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27, long c28, long c29, long c30, long c31, long c32, long c33, long c34, long c35, long c36, long c37) {
+ long t0;
+
+ //reduce from position 19
+ t0 = -20472841 * c19;
+ c0 += (t0 << 11) & LIMB_MASK;
+ c1 += t0 >> 17;
+ t0 = -117141993 * c19;
+ c1 += (t0 << 11) & LIMB_MASK;
+ c2 += t0 >> 17;
+ t0 = 62411077 * c19;
+ c2 += (t0 << 11) & LIMB_MASK;
+ c3 += t0 >> 17;
+ t0 = 56915814 * c19;
+ c3 += (t0 << 11) & LIMB_MASK;
+ c4 += t0 >> 17;
+ t0 = -97532854 * c19;
+ c4 += (t0 << 11) & LIMB_MASK;
+ c5 += t0 >> 17;
+ t0 = -76509338 * c19;
+ c5 += (t0 << 11) & LIMB_MASK;
+ c6 += t0 >> 17;
+ t0 = 75510783 * c19;
+ c6 += (t0 << 11) & LIMB_MASK;
+ c7 += t0 >> 17;
+ t0 = 67962521 * c19;
+ c7 += (t0 << 11) & LIMB_MASK;
+ c8 += t0 >> 17;
+ t0 = -25593732 * c19;
+ c8 += (t0 << 11) & LIMB_MASK;
+ c9 += t0 >> 17;
+ t0 = 91 * c19;
+ c9 += (t0 << 11) & LIMB_MASK;
+ c10 += t0 >> 17;
+ //carry from position 0
+ t0 = (c0 + CARRY_ADD) >> 28;
+ c0 -= (t0 << 28);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 28;
+ c1 -= (t0 << 28);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 28;
+ c2 -= (t0 << 28);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 28;
+ c3 -= (t0 << 28);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 28;
+ c4 -= (t0 << 28);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 28;
+ c5 -= (t0 << 28);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 28;
+ c6 -= (t0 << 28);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 28;
+ c7 -= (t0 << 28);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 28;
+ c8 -= (t0 << 28);
+ c9 += t0;
+ //carry from position 9
+ t0 = (c9 + CARRY_ADD) >> 28;
+ c9 -= (t0 << 28);
+ c10 += t0;
+ //carry from position 10
+ t0 = (c10 + CARRY_ADD) >> 28;
+ c10 -= (t0 << 28);
+ c11 += t0;
+ //carry from position 11
+ t0 = (c11 + CARRY_ADD) >> 28;
+ c11 -= (t0 << 28);
+ c12 += t0;
+ //carry from position 12
+ t0 = (c12 + CARRY_ADD) >> 28;
+ c12 -= (t0 << 28);
+ c13 += t0;
+ //carry from position 13
+ t0 = (c13 + CARRY_ADD) >> 28;
+ c13 -= (t0 << 28);
+ c14 += t0;
+ //carry from position 14
+ t0 = (c14 + CARRY_ADD) >> 28;
+ c14 -= (t0 << 28);
+ c15 += t0;
+ //carry from position 15
+ t0 = (c15 + CARRY_ADD) >> 28;
+ c15 -= (t0 << 28);
+ c16 += t0;
+ //carry from position 16
+ t0 = (c16 + CARRY_ADD) >> 28;
+ c16 -= (t0 << 28);
+ c17 += t0;
+ //carry from position 17
+ t0 = (c17 + CARRY_ADD) >> 28;
+ c17 -= (t0 << 28);
+ c18 += t0;
+
+ r[0] = c0;
+ r[1] = c1;
+ r[2] = c2;
+ r[3] = c3;
+ r[4] = c4;
+ r[5] = c5;
+ r[6] = c6;
+ r[7] = c7;
+ r[8] = c8;
+ r[9] = c9;
+ r[10] = c10;
+ r[11] = c11;
+ r[12] = c12;
+ r[13] = c13;
+ r[14] = c14;
+ r[15] = c15;
+ r[16] = c16;
+ r[17] = c17;
+ r[18] = c18;
+ }
+ private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18) {
+ long c19 = 0;
+ //carry from position 0
+ long t0 = (c0 + CARRY_ADD) >> 28;
+ c0 -= (t0 << 28);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 28;
+ c1 -= (t0 << 28);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 28;
+ c2 -= (t0 << 28);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 28;
+ c3 -= (t0 << 28);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 28;
+ c4 -= (t0 << 28);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 28;
+ c5 -= (t0 << 28);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 28;
+ c6 -= (t0 << 28);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 28;
+ c7 -= (t0 << 28);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 28;
+ c8 -= (t0 << 28);
+ c9 += t0;
+ //carry from position 9
+ t0 = (c9 + CARRY_ADD) >> 28;
+ c9 -= (t0 << 28);
+ c10 += t0;
+ //carry from position 10
+ t0 = (c10 + CARRY_ADD) >> 28;
+ c10 -= (t0 << 28);
+ c11 += t0;
+ //carry from position 11
+ t0 = (c11 + CARRY_ADD) >> 28;
+ c11 -= (t0 << 28);
+ c12 += t0;
+ //carry from position 12
+ t0 = (c12 + CARRY_ADD) >> 28;
+ c12 -= (t0 << 28);
+ c13 += t0;
+ //carry from position 13
+ t0 = (c13 + CARRY_ADD) >> 28;
+ c13 -= (t0 << 28);
+ c14 += t0;
+ //carry from position 14
+ t0 = (c14 + CARRY_ADD) >> 28;
+ c14 -= (t0 << 28);
+ c15 += t0;
+ //carry from position 15
+ t0 = (c15 + CARRY_ADD) >> 28;
+ c15 -= (t0 << 28);
+ c16 += t0;
+ //carry from position 16
+ t0 = (c16 + CARRY_ADD) >> 28;
+ c16 -= (t0 << 28);
+ c17 += t0;
+ //carry from position 17
+ t0 = (c17 + CARRY_ADD) >> 28;
+ c17 -= (t0 << 28);
+ c18 += t0;
+ //carry from position 18
+ t0 = (c18 + CARRY_ADD) >> 28;
+ c18 -= (t0 << 28);
+ c19 += t0;
+
+ carryReduce0(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19);
+ }
+ void carryReduce0(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19) {
+ long t0;
+
+ //reduce from position 19
+ t0 = -20472841 * c19;
+ c0 += (t0 << 11) & LIMB_MASK;
+ c1 += t0 >> 17;
+ t0 = -117141993 * c19;
+ c1 += (t0 << 11) & LIMB_MASK;
+ c2 += t0 >> 17;
+ t0 = 62411077 * c19;
+ c2 += (t0 << 11) & LIMB_MASK;
+ c3 += t0 >> 17;
+ t0 = 56915814 * c19;
+ c3 += (t0 << 11) & LIMB_MASK;
+ c4 += t0 >> 17;
+ t0 = -97532854 * c19;
+ c4 += (t0 << 11) & LIMB_MASK;
+ c5 += t0 >> 17;
+ t0 = -76509338 * c19;
+ c5 += (t0 << 11) & LIMB_MASK;
+ c6 += t0 >> 17;
+ t0 = 75510783 * c19;
+ c6 += (t0 << 11) & LIMB_MASK;
+ c7 += t0 >> 17;
+ t0 = 67962521 * c19;
+ c7 += (t0 << 11) & LIMB_MASK;
+ c8 += t0 >> 17;
+ t0 = -25593732 * c19;
+ c8 += (t0 << 11) & LIMB_MASK;
+ c9 += t0 >> 17;
+ t0 = 91 * c19;
+ c9 += (t0 << 11) & LIMB_MASK;
+ c10 += t0 >> 17;
+ //carry from position 0
+ t0 = (c0 + CARRY_ADD) >> 28;
+ c0 -= (t0 << 28);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 28;
+ c1 -= (t0 << 28);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 28;
+ c2 -= (t0 << 28);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 28;
+ c3 -= (t0 << 28);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 28;
+ c4 -= (t0 << 28);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 28;
+ c5 -= (t0 << 28);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 28;
+ c6 -= (t0 << 28);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 28;
+ c7 -= (t0 << 28);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 28;
+ c8 -= (t0 << 28);
+ c9 += t0;
+ //carry from position 9
+ t0 = (c9 + CARRY_ADD) >> 28;
+ c9 -= (t0 << 28);
+ c10 += t0;
+ //carry from position 10
+ t0 = (c10 + CARRY_ADD) >> 28;
+ c10 -= (t0 << 28);
+ c11 += t0;
+ //carry from position 11
+ t0 = (c11 + CARRY_ADD) >> 28;
+ c11 -= (t0 << 28);
+ c12 += t0;
+ //carry from position 12
+ t0 = (c12 + CARRY_ADD) >> 28;
+ c12 -= (t0 << 28);
+ c13 += t0;
+ //carry from position 13
+ t0 = (c13 + CARRY_ADD) >> 28;
+ c13 -= (t0 << 28);
+ c14 += t0;
+ //carry from position 14
+ t0 = (c14 + CARRY_ADD) >> 28;
+ c14 -= (t0 << 28);
+ c15 += t0;
+ //carry from position 15
+ t0 = (c15 + CARRY_ADD) >> 28;
+ c15 -= (t0 << 28);
+ c16 += t0;
+ //carry from position 16
+ t0 = (c16 + CARRY_ADD) >> 28;
+ c16 -= (t0 << 28);
+ c17 += t0;
+ //carry from position 17
+ t0 = (c17 + CARRY_ADD) >> 28;
+ c17 -= (t0 << 28);
+ c18 += t0;
+
+ r[0] = c0;
+ r[1] = c1;
+ r[2] = c2;
+ r[3] = c3;
+ r[4] = c4;
+ r[5] = c5;
+ r[6] = c6;
+ r[7] = c7;
+ r[8] = c8;
+ r[9] = c9;
+ r[10] = c10;
+ r[11] = c11;
+ r[12] = c12;
+ r[13] = c13;
+ r[14] = c14;
+ r[15] = c15;
+ r[16] = c16;
+ r[17] = c17;
+ r[18] = c18;
+ }
+ @Override
+ protected void mult(long[] a, long[] b, long[] r) {
+ long c0 = (a[0] * b[0]);
+ long c1 = (a[0] * b[1]) + (a[1] * b[0]);
+ long c2 = (a[0] * b[2]) + (a[1] * b[1]) + (a[2] * b[0]);
+ long c3 = (a[0] * b[3]) + (a[1] * b[2]) + (a[2] * b[1]) + (a[3] * b[0]);
+ long c4 = (a[0] * b[4]) + (a[1] * b[3]) + (a[2] * b[2]) + (a[3] * b[1]) + (a[4] * b[0]);
+ long c5 = (a[0] * b[5]) + (a[1] * b[4]) + (a[2] * b[3]) + (a[3] * b[2]) + (a[4] * b[1]) + (a[5] * b[0]);
+ long c6 = (a[0] * b[6]) + (a[1] * b[5]) + (a[2] * b[4]) + (a[3] * b[3]) + (a[4] * b[2]) + (a[5] * b[1]) + (a[6] * b[0]);
+ long c7 = (a[0] * b[7]) + (a[1] * b[6]) + (a[2] * b[5]) + (a[3] * b[4]) + (a[4] * b[3]) + (a[5] * b[2]) + (a[6] * b[1]) + (a[7] * b[0]);
+ long c8 = (a[0] * b[8]) + (a[1] * b[7]) + (a[2] * b[6]) + (a[3] * b[5]) + (a[4] * b[4]) + (a[5] * b[3]) + (a[6] * b[2]) + (a[7] * b[1]) + (a[8] * b[0]);
+ long c9 = (a[0] * b[9]) + (a[1] * b[8]) + (a[2] * b[7]) + (a[3] * b[6]) + (a[4] * b[5]) + (a[5] * b[4]) + (a[6] * b[3]) + (a[7] * b[2]) + (a[8] * b[1]) + (a[9] * b[0]);
+ long c10 = (a[0] * b[10]) + (a[1] * b[9]) + (a[2] * b[8]) + (a[3] * b[7]) + (a[4] * b[6]) + (a[5] * b[5]) + (a[6] * b[4]) + (a[7] * b[3]) + (a[8] * b[2]) + (a[9] * b[1]) + (a[10] * b[0]);
+ long c11 = (a[0] * b[11]) + (a[1] * b[10]) + (a[2] * b[9]) + (a[3] * b[8]) + (a[4] * b[7]) + (a[5] * b[6]) + (a[6] * b[5]) + (a[7] * b[4]) + (a[8] * b[3]) + (a[9] * b[2]) + (a[10] * b[1]) + (a[11] * b[0]);
+ long c12 = (a[0] * b[12]) + (a[1] * b[11]) + (a[2] * b[10]) + (a[3] * b[9]) + (a[4] * b[8]) + (a[5] * b[7]) + (a[6] * b[6]) + (a[7] * b[5]) + (a[8] * b[4]) + (a[9] * b[3]) + (a[10] * b[2]) + (a[11] * b[1]) + (a[12] * b[0]);
+ long c13 = (a[0] * b[13]) + (a[1] * b[12]) + (a[2] * b[11]) + (a[3] * b[10]) + (a[4] * b[9]) + (a[5] * b[8]) + (a[6] * b[7]) + (a[7] * b[6]) + (a[8] * b[5]) + (a[9] * b[4]) + (a[10] * b[3]) + (a[11] * b[2]) + (a[12] * b[1]) + (a[13] * b[0]);
+ long c14 = (a[0] * b[14]) + (a[1] * b[13]) + (a[2] * b[12]) + (a[3] * b[11]) + (a[4] * b[10]) + (a[5] * b[9]) + (a[6] * b[8]) + (a[7] * b[7]) + (a[8] * b[6]) + (a[9] * b[5]) + (a[10] * b[4]) + (a[11] * b[3]) + (a[12] * b[2]) + (a[13] * b[1]) + (a[14] * b[0]);
+ long c15 = (a[0] * b[15]) + (a[1] * b[14]) + (a[2] * b[13]) + (a[3] * b[12]) + (a[4] * b[11]) + (a[5] * b[10]) + (a[6] * b[9]) + (a[7] * b[8]) + (a[8] * b[7]) + (a[9] * b[6]) + (a[10] * b[5]) + (a[11] * b[4]) + (a[12] * b[3]) + (a[13] * b[2]) + (a[14] * b[1]) + (a[15] * b[0]);
+ long c16 = (a[0] * b[16]) + (a[1] * b[15]) + (a[2] * b[14]) + (a[3] * b[13]) + (a[4] * b[12]) + (a[5] * b[11]) + (a[6] * b[10]) + (a[7] * b[9]) + (a[8] * b[8]) + (a[9] * b[7]) + (a[10] * b[6]) + (a[11] * b[5]) + (a[12] * b[4]) + (a[13] * b[3]) + (a[14] * b[2]) + (a[15] * b[1]) + (a[16] * b[0]);
+ long c17 = (a[0] * b[17]) + (a[1] * b[16]) + (a[2] * b[15]) + (a[3] * b[14]) + (a[4] * b[13]) + (a[5] * b[12]) + (a[6] * b[11]) + (a[7] * b[10]) + (a[8] * b[9]) + (a[9] * b[8]) + (a[10] * b[7]) + (a[11] * b[6]) + (a[12] * b[5]) + (a[13] * b[4]) + (a[14] * b[3]) + (a[15] * b[2]) + (a[16] * b[1]) + (a[17] * b[0]);
+ long c18 = (a[0] * b[18]) + (a[1] * b[17]) + (a[2] * b[16]) + (a[3] * b[15]) + (a[4] * b[14]) + (a[5] * b[13]) + (a[6] * b[12]) + (a[7] * b[11]) + (a[8] * b[10]) + (a[9] * b[9]) + (a[10] * b[8]) + (a[11] * b[7]) + (a[12] * b[6]) + (a[13] * b[5]) + (a[14] * b[4]) + (a[15] * b[3]) + (a[16] * b[2]) + (a[17] * b[1]) + (a[18] * b[0]);
+ long c19 = (a[1] * b[18]) + (a[2] * b[17]) + (a[3] * b[16]) + (a[4] * b[15]) + (a[5] * b[14]) + (a[6] * b[13]) + (a[7] * b[12]) + (a[8] * b[11]) + (a[9] * b[10]) + (a[10] * b[9]) + (a[11] * b[8]) + (a[12] * b[7]) + (a[13] * b[6]) + (a[14] * b[5]) + (a[15] * b[4]) + (a[16] * b[3]) + (a[17] * b[2]) + (a[18] * b[1]);
+ long c20 = (a[2] * b[18]) + (a[3] * b[17]) + (a[4] * b[16]) + (a[5] * b[15]) + (a[6] * b[14]) + (a[7] * b[13]) + (a[8] * b[12]) + (a[9] * b[11]) + (a[10] * b[10]) + (a[11] * b[9]) + (a[12] * b[8]) + (a[13] * b[7]) + (a[14] * b[6]) + (a[15] * b[5]) + (a[16] * b[4]) + (a[17] * b[3]) + (a[18] * b[2]);
+ long c21 = (a[3] * b[18]) + (a[4] * b[17]) + (a[5] * b[16]) + (a[6] * b[15]) + (a[7] * b[14]) + (a[8] * b[13]) + (a[9] * b[12]) + (a[10] * b[11]) + (a[11] * b[10]) + (a[12] * b[9]) + (a[13] * b[8]) + (a[14] * b[7]) + (a[15] * b[6]) + (a[16] * b[5]) + (a[17] * b[4]) + (a[18] * b[3]);
+ long c22 = (a[4] * b[18]) + (a[5] * b[17]) + (a[6] * b[16]) + (a[7] * b[15]) + (a[8] * b[14]) + (a[9] * b[13]) + (a[10] * b[12]) + (a[11] * b[11]) + (a[12] * b[10]) + (a[13] * b[9]) + (a[14] * b[8]) + (a[15] * b[7]) + (a[16] * b[6]) + (a[17] * b[5]) + (a[18] * b[4]);
+ long c23 = (a[5] * b[18]) + (a[6] * b[17]) + (a[7] * b[16]) + (a[8] * b[15]) + (a[9] * b[14]) + (a[10] * b[13]) + (a[11] * b[12]) + (a[12] * b[11]) + (a[13] * b[10]) + (a[14] * b[9]) + (a[15] * b[8]) + (a[16] * b[7]) + (a[17] * b[6]) + (a[18] * b[5]);
+ long c24 = (a[6] * b[18]) + (a[7] * b[17]) + (a[8] * b[16]) + (a[9] * b[15]) + (a[10] * b[14]) + (a[11] * b[13]) + (a[12] * b[12]) + (a[13] * b[11]) + (a[14] * b[10]) + (a[15] * b[9]) + (a[16] * b[8]) + (a[17] * b[7]) + (a[18] * b[6]);
+ long c25 = (a[7] * b[18]) + (a[8] * b[17]) + (a[9] * b[16]) + (a[10] * b[15]) + (a[11] * b[14]) + (a[12] * b[13]) + (a[13] * b[12]) + (a[14] * b[11]) + (a[15] * b[10]) + (a[16] * b[9]) + (a[17] * b[8]) + (a[18] * b[7]);
+ long c26 = (a[8] * b[18]) + (a[9] * b[17]) + (a[10] * b[16]) + (a[11] * b[15]) + (a[12] * b[14]) + (a[13] * b[13]) + (a[14] * b[12]) + (a[15] * b[11]) + (a[16] * b[10]) + (a[17] * b[9]) + (a[18] * b[8]);
+ long c27 = (a[9] * b[18]) + (a[10] * b[17]) + (a[11] * b[16]) + (a[12] * b[15]) + (a[13] * b[14]) + (a[14] * b[13]) + (a[15] * b[12]) + (a[16] * b[11]) + (a[17] * b[10]) + (a[18] * b[9]);
+ long c28 = (a[10] * b[18]) + (a[11] * b[17]) + (a[12] * b[16]) + (a[13] * b[15]) + (a[14] * b[14]) + (a[15] * b[13]) + (a[16] * b[12]) + (a[17] * b[11]) + (a[18] * b[10]);
+ long c29 = (a[11] * b[18]) + (a[12] * b[17]) + (a[13] * b[16]) + (a[14] * b[15]) + (a[15] * b[14]) + (a[16] * b[13]) + (a[17] * b[12]) + (a[18] * b[11]);
+ long c30 = (a[12] * b[18]) + (a[13] * b[17]) + (a[14] * b[16]) + (a[15] * b[15]) + (a[16] * b[14]) + (a[17] * b[13]) + (a[18] * b[12]);
+ long c31 = (a[13] * b[18]) + (a[14] * b[17]) + (a[15] * b[16]) + (a[16] * b[15]) + (a[17] * b[14]) + (a[18] * b[13]);
+ long c32 = (a[14] * b[18]) + (a[15] * b[17]) + (a[16] * b[16]) + (a[17] * b[15]) + (a[18] * b[14]);
+ long c33 = (a[15] * b[18]) + (a[16] * b[17]) + (a[17] * b[16]) + (a[18] * b[15]);
+ long c34 = (a[16] * b[18]) + (a[17] * b[17]) + (a[18] * b[16]);
+ long c35 = (a[17] * b[18]) + (a[18] * b[17]);
+ long c36 = (a[18] * b[18]);
+
+ carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30, c31, c32, c33, c34, c35, c36);
+ }
+ @Override
+ protected void reduce(long[] a) {
+ carryReduce(a, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15], a[16], a[17], a[18]);
+ }
+ @Override
+ protected void square(long[] a, long[] r) {
+ long c0 = (a[0] * a[0]);
+ long c1 = 2 * ((a[0] * a[1]));
+ long c2 = 2 * ((a[0] * a[2])) + (a[1] * a[1]);
+ long c3 = 2 * ((a[0] * a[3]) + (a[1] * a[2]));
+ long c4 = 2 * ((a[0] * a[4]) + (a[1] * a[3])) + (a[2] * a[2]);
+ long c5 = 2 * ((a[0] * a[5]) + (a[1] * a[4]) + (a[2] * a[3]));
+ long c6 = 2 * ((a[0] * a[6]) + (a[1] * a[5]) + (a[2] * a[4])) + (a[3] * a[3]);
+ long c7 = 2 * ((a[0] * a[7]) + (a[1] * a[6]) + (a[2] * a[5]) + (a[3] * a[4]));
+ long c8 = 2 * ((a[0] * a[8]) + (a[1] * a[7]) + (a[2] * a[6]) + (a[3] * a[5])) + (a[4] * a[4]);
+ long c9 = 2 * ((a[0] * a[9]) + (a[1] * a[8]) + (a[2] * a[7]) + (a[3] * a[6]) + (a[4] * a[5]));
+ long c10 = 2 * ((a[0] * a[10]) + (a[1] * a[9]) + (a[2] * a[8]) + (a[3] * a[7]) + (a[4] * a[6])) + (a[5] * a[5]);
+ long c11 = 2 * ((a[0] * a[11]) + (a[1] * a[10]) + (a[2] * a[9]) + (a[3] * a[8]) + (a[4] * a[7]) + (a[5] * a[6]));
+ long c12 = 2 * ((a[0] * a[12]) + (a[1] * a[11]) + (a[2] * a[10]) + (a[3] * a[9]) + (a[4] * a[8]) + (a[5] * a[7])) + (a[6] * a[6]);
+ long c13 = 2 * ((a[0] * a[13]) + (a[1] * a[12]) + (a[2] * a[11]) + (a[3] * a[10]) + (a[4] * a[9]) + (a[5] * a[8]) + (a[6] * a[7]));
+ long c14 = 2 * ((a[0] * a[14]) + (a[1] * a[13]) + (a[2] * a[12]) + (a[3] * a[11]) + (a[4] * a[10]) + (a[5] * a[9]) + (a[6] * a[8])) + (a[7] * a[7]);
+ long c15 = 2 * ((a[0] * a[15]) + (a[1] * a[14]) + (a[2] * a[13]) + (a[3] * a[12]) + (a[4] * a[11]) + (a[5] * a[10]) + (a[6] * a[9]) + (a[7] * a[8]));
+ long c16 = 2 * ((a[0] * a[16]) + (a[1] * a[15]) + (a[2] * a[14]) + (a[3] * a[13]) + (a[4] * a[12]) + (a[5] * a[11]) + (a[6] * a[10]) + (a[7] * a[9])) + (a[8] * a[8]);
+ long c17 = 2 * ((a[0] * a[17]) + (a[1] * a[16]) + (a[2] * a[15]) + (a[3] * a[14]) + (a[4] * a[13]) + (a[5] * a[12]) + (a[6] * a[11]) + (a[7] * a[10]) + (a[8] * a[9]));
+ long c18 = 2 * ((a[0] * a[18]) + (a[1] * a[17]) + (a[2] * a[16]) + (a[3] * a[15]) + (a[4] * a[14]) + (a[5] * a[13]) + (a[6] * a[12]) + (a[7] * a[11]) + (a[8] * a[10])) + (a[9] * a[9]);
+ long c19 = 2 * ((a[1] * a[18]) + (a[2] * a[17]) + (a[3] * a[16]) + (a[4] * a[15]) + (a[5] * a[14]) + (a[6] * a[13]) + (a[7] * a[12]) + (a[8] * a[11]) + (a[9] * a[10]));
+ long c20 = 2 * ((a[2] * a[18]) + (a[3] * a[17]) + (a[4] * a[16]) + (a[5] * a[15]) + (a[6] * a[14]) + (a[7] * a[13]) + (a[8] * a[12]) + (a[9] * a[11])) + (a[10] * a[10]);
+ long c21 = 2 * ((a[3] * a[18]) + (a[4] * a[17]) + (a[5] * a[16]) + (a[6] * a[15]) + (a[7] * a[14]) + (a[8] * a[13]) + (a[9] * a[12]) + (a[10] * a[11]));
+ long c22 = 2 * ((a[4] * a[18]) + (a[5] * a[17]) + (a[6] * a[16]) + (a[7] * a[15]) + (a[8] * a[14]) + (a[9] * a[13]) + (a[10] * a[12])) + (a[11] * a[11]);
+ long c23 = 2 * ((a[5] * a[18]) + (a[6] * a[17]) + (a[7] * a[16]) + (a[8] * a[15]) + (a[9] * a[14]) + (a[10] * a[13]) + (a[11] * a[12]));
+ long c24 = 2 * ((a[6] * a[18]) + (a[7] * a[17]) + (a[8] * a[16]) + (a[9] * a[15]) + (a[10] * a[14]) + (a[11] * a[13])) + (a[12] * a[12]);
+ long c25 = 2 * ((a[7] * a[18]) + (a[8] * a[17]) + (a[9] * a[16]) + (a[10] * a[15]) + (a[11] * a[14]) + (a[12] * a[13]));
+ long c26 = 2 * ((a[8] * a[18]) + (a[9] * a[17]) + (a[10] * a[16]) + (a[11] * a[15]) + (a[12] * a[14])) + (a[13] * a[13]);
+ long c27 = 2 * ((a[9] * a[18]) + (a[10] * a[17]) + (a[11] * a[16]) + (a[12] * a[15]) + (a[13] * a[14]));
+ long c28 = 2 * ((a[10] * a[18]) + (a[11] * a[17]) + (a[12] * a[16]) + (a[13] * a[15])) + (a[14] * a[14]);
+ long c29 = 2 * ((a[11] * a[18]) + (a[12] * a[17]) + (a[13] * a[16]) + (a[14] * a[15]));
+ long c30 = 2 * ((a[12] * a[18]) + (a[13] * a[17]) + (a[14] * a[16])) + (a[15] * a[15]);
+ long c31 = 2 * ((a[13] * a[18]) + (a[14] * a[17]) + (a[15] * a[16]));
+ long c32 = 2 * ((a[14] * a[18]) + (a[15] * a[17])) + (a[16] * a[16]);
+ long c33 = 2 * ((a[15] * a[18]) + (a[16] * a[17]));
+ long c34 = 2 * ((a[16] * a[18])) + (a[17] * a[17]);
+ long c35 = 2 * ((a[17] * a[18]));
+ long c36 = (a[18] * a[18]);
+
+ carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30, c31, c32, c33, c34, c35, c36);
+ }
+}
+
diff -r a659ccd1888d -r ddbd9744a3d5 src/java.base/share/classes/sun/security/util/math/intpoly/header.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/util/math/intpoly/header.txt Wed Dec 12 15:04:47 2018 +0530
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is generated by FieldGen.jsh. Do not modify it directly.
+ */
diff -r a659ccd1888d -r ddbd9744a3d5 src/java.base/share/classes/sun/security/validator/CADistrustPolicy.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/validator/CADistrustPolicy.java Wed Dec 12 15:04:47 2018 +0530
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package sun.security.validator;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.Security;
+import java.security.cert.X509Certificate;
+import java.util.EnumSet;
+
+import sun.security.util.Debug;
+
+/**
+ * Policies for distrusting a certificate authority (CA). See the
+ * jdk.security.caDistrustPolicies security property for more information.
+ */
+enum CADistrustPolicy {
+ /**
+ * Distrust TLS Server certificates anchored by a Symantec root CA and
+ * issued after April 16, 2019. If enabled, this policy is currently
+ * enforced by the PKIX and SunX509 TrustManager implementations of the
+ * SunJSSE provider implementation.
+ */
+ SYMANTEC_TLS {
+ void checkDistrust(String variant, X509Certificate anchor,
+ X509Certificate ee) throws ValidatorException {
+ if (!variant.equals(Validator.VAR_TLS_SERVER)) {
+ return;
+ }
+ SymantecTLSPolicy.checkDistrust(anchor, ee);
+ }
+ };
+
+ /**
+ * Checks if the end-entity certificate is distrusted.
+ *
+ * @param variant the type of certificate being checked
+ * @param anchor the trust anchor certificate
+ * @param ee the end-entity certificate to check
+ * @throws ValidatorException if the end-entity certificate is distrusted
+ */
+ abstract void checkDistrust(String variant,
+ X509Certificate anchor,
+ X509Certificate ee) throws ValidatorException;
+
+ // The policies set in the jdk.security.caDistrustPolicies property.
+ static final EnumSet POLICIES = parseProperty();
+ private static EnumSet parseProperty() {
+ String property = AccessController.doPrivileged(
+ new PrivilegedAction<>() {
+ @Override
+ public String run() {
+ return Security.getProperty(
+ "jdk.security.caDistrustPolicies");
+ }
+ });
+ EnumSet set = EnumSet.noneOf(CADistrustPolicy.class);
+ // if property is null or empty, the restrictions are not enforced
+ if (property == null || property.isEmpty()) {
+ return set;
+ }
+ String[] policies = property.split(",");
+ for (String policy : policies) {
+ policy = policy.trim();
+ try {
+ CADistrustPolicy caPolicy =
+ Enum.valueOf(CADistrustPolicy.class, policy);
+ set.add(caPolicy);
+ } catch (IllegalArgumentException iae) {
+ // ignore unknown values but log it
+ Debug debug = Debug.getInstance("certpath");
+ if (debug != null) {
+ debug.println("Unknown value for the " +
+ "jdk.security.caDistrustPolicies property: "
+ + policy);
+ }
+ }
+ }
+ return set;
+ }
+}
diff -r a659ccd1888d -r ddbd9744a3d5 src/java.base/share/classes/sun/security/validator/EndEntityChecker.java
--- a/src/java.base/share/classes/sun/security/validator/EndEntityChecker.java Tue Dec 11 11:45:43 2018 +0530
+++ b/src/java.base/share/classes/sun/security/validator/EndEntityChecker.java Wed Dec 12 15:04:47 2018 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -133,7 +133,9 @@
}
void check(X509Certificate cert, Object parameter,
- boolean checkUnresolvedCritExts) throws CertificateException {
+ boolean checkUnresolvedCritExts, X509Certificate anchor)
+ throws CertificateException {
+
if (variant.equals(Validator.VAR_GENERIC)) {
return; // no checks
}
@@ -159,6 +161,12 @@
if (checkUnresolvedCritExts) {
checkRemainingExtensions(exts);
}
+
+ // check if certificate should be distrusted according to policies
+ // set in the jdk.security.caDistrustPolicies security property
+ for (CADistrustPolicy policy : CADistrustPolicy.POLICIES) {
+ policy.checkDistrust(variant, anchor, cert);
+ }
}
/**
diff -r a659ccd1888d -r ddbd9744a3d5 src/java.base/share/classes/sun/security/validator/SymantecTLSPolicy.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/validator/SymantecTLSPolicy.java Wed Dec 12 15:04:47 2018 +0530
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package sun.security.validator;
+
+import java.security.cert.X509Certificate;
+import java.time.LocalDate;
+import java.time.Month;
+import java.time.ZoneOffset;
+import java.util.Date;
+import java.util.Set;
+
+import sun.security.x509.X509CertImpl;
+
+/**
+ * This class checks if Symantec issued TLS Server certificates should be
+ * restricted.
+ */
+final class SymantecTLSPolicy {
+
+ // SHA-256 certificate fingerprints of distrusted roots
+ private static final Set FINGERPRINTS = Set.of(
+ // cacerts alias: geotrustglobalca
+ // DN: CN=GeoTrust Global CA, O=GeoTrust Inc., C=US
+ "FF856A2D251DCD88D36656F450126798CFABAADE40799C722DE4D2B5DB36A73A",
+ // cacerts alias: geotrustprimaryca
+ // DN: CN=GeoTrust Primary Certification Authority,
+ // O=GeoTrust Inc., C=US
+ "37D51006C512EAAB626421F1EC8C92013FC5F82AE98EE533EB4619B8DEB4D06C",
+ // cacerts alias: geotrustprimarycag2
+ // DN: CN=GeoTrust Primary Certification Authority - G2,
+ // OU=(c) 2007 GeoTrust Inc. - For authorized use only,
+ // O=GeoTrust Inc., C=US
+ "5EDB7AC43B82A06A8761E8D7BE4979EBF2611F7DD79BF91C1C6B566A219ED766",
+ // cacerts alias: geotrustprimarycag3
+ // DN: CN=GeoTrust Primary Certification Authority - G3,
+ // OU=(c) 2008 GeoTrust Inc. - For authorized use only,
+ // O=GeoTrust Inc., C=US
+ "B478B812250DF878635C2AA7EC7D155EAA625EE82916E2CD294361886CD1FBD4",
+ // cacerts alias: geotrustuniversalca
+ // DN: CN=GeoTrust Universal CA, O=GeoTrust Inc., C=US
+ "A0459B9F63B22559F5FA5D4C6DB3F9F72FF19342033578F073BF1D1B46CBB912",
+ // cacerts alias: thawteprimaryrootca
+ // DN: CN=thawte Primary Root CA,
+ // OU="(c) 2006 thawte, Inc. - For authorized use only",
+ // OU=Certification Services Division, O="thawte, Inc.", C=US
+ "8D722F81A9C113C0791DF136A2966DB26C950A971DB46B4199F4EA54B78BFB9F",
+ // cacerts alias: thawteprimaryrootcag2
+ // DN: CN=thawte Primary Root CA - G2,
+ // OU="(c) 2007 thawte, Inc. - For authorized use only",
+ // O="thawte, Inc.", C=US
+ "A4310D50AF18A6447190372A86AFAF8B951FFB431D837F1E5688B45971ED1557",
+ // cacerts alias: thawteprimaryrootcag3
+ // DN: CN=thawte Primary Root CA - G3,
+ // OU="(c) 2008 thawte, Inc. - For authorized use only",
+ // OU=Certification Services Division, O="thawte, Inc.", C=US
+ "4B03F45807AD70F21BFC2CAE71C9FDE4604C064CF5FFB686BAE5DBAAD7FDD34C",
+ // cacerts alias: thawtepremiumserverca
+ // DN: EMAILADDRESS=premium-server@thawte.com,
+ // CN=Thawte Premium Server CA, OU=Certification Services Division,
+ // O=Thawte Consulting cc, L=Cape Town, ST=Western Cape, C=ZA
+ "3F9F27D583204B9E09C8A3D2066C4B57D3A2479C3693650880505698105DBCE9",
+ // cacerts alias: verisignclass2g2ca
+ // DN: OU=VeriSign Trust Network,
+ // OU="(c) 1998 VeriSign, Inc. - For authorized use only",
+ // OU=Class 2 Public Primary Certification Authority - G2,
+ // O="VeriSign, Inc.", C=US
+ "3A43E220FE7F3EA9653D1E21742EAC2B75C20FD8980305BC502CAF8C2D9B41A1",
+ // cacerts alias: verisignclass3ca
+ // DN: OU=Class 3 Public Primary Certification Authority,
+ // O="VeriSign, Inc.", C=US
+ "A4B6B3996FC2F306B3FD8681BD63413D8C5009CC4FA329C2CCF0E2FA1B140305",
+ // cacerts alias: verisignclass3g2ca
+ // DN: OU=VeriSign Trust Network,
+ // OU="(c) 1998 VeriSign, Inc. - For authorized use only",
+ // OU=Class 3 Public Primary Certification Authority - G2,
+ // O="VeriSign, Inc.", C=US
+ "83CE3C1229688A593D485F81973C0F9195431EDA37CC5E36430E79C7A888638B",
+ // cacerts alias: verisignclass3g3ca
+ // DN: CN=VeriSign Class 3 Public Primary Certification Authority - G3,
+ // OU="(c) 1999 VeriSign, Inc. - For authorized use only",
+ // OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US
+ "EB04CF5EB1F39AFA762F2BB120F296CBA520C1B97DB1589565B81CB9A17B7244",
+ // cacerts alias: verisignclass3g4ca
+ // DN: CN=VeriSign Class 3 Public Primary Certification Authority - G4,
+ // OU="(c) 2007 VeriSign, Inc. - For authorized use only",
+ // OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US
+ "69DDD7EA90BB57C93E135DC85EA6FCD5480B603239BDC454FC758B2A26CF7F79",
+ // cacerts alias: verisignclass3g5ca
+ // DN: CN=VeriSign Class 3 Public Primary Certification Authority - G5,
+ // OU="(c) 2006 VeriSign, Inc. - For authorized use only",
+ // OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US
+ "9ACFAB7E43C8D880D06B262A94DEEEE4B4659989C3D0CAF19BAF6405E41AB7DF",
+ // cacerts alias: verisignuniversalrootca
+ // DN: CN=VeriSign Universal Root Certification Authority,
+ // OU="(c) 2008 VeriSign, Inc. - For authorized use only",
+ // OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US
+ "2399561127A57125DE8CEFEA610DDF2FA078B5C8067F4E828290BFB860E84B3C"
+ );
+
+ // Any TLS Server certificate that is anchored by one of the Symantec
+ // roots above and is issued after this date will be distrusted.
+ private static final LocalDate APRIL_16_2019 =
+ LocalDate.of(2019, Month.APRIL, 16);
+
+ /**
+ * This method assumes the eeCert is a TLS Server Cert and chains back to
+ * the anchor.
+ *
+ * @param anchor the trust anchor certificate
+ * @param eeCert the certificate to check
+ * @throws ValidatorException if the certificate is distrusted
+ */
+ static void checkDistrust(X509Certificate anchor,
+ X509Certificate eeCert)
+ throws ValidatorException {
+ String fp = (anchor instanceof X509CertImpl)
+ ? ((X509CertImpl)anchor).getFingerprint("SHA-256")
+ : X509CertImpl.getFingerprint("SHA-256", anchor);
+ if (FINGERPRINTS.contains(fp)) {
+ // reject if certificate is issued after April 16, 2019
+ Date notBefore = eeCert.getNotBefore();
+ LocalDate ldNotBefore = LocalDate.ofInstant(notBefore.toInstant(),
+ ZoneOffset.UTC);
+ if (ldNotBefore.isAfter(APRIL_16_2019)) {
+ throw new ValidatorException
+ ("TLS Server certificate issued after " + APRIL_16_2019 +
+ " and anchored by a distrusted legacy Symantec root CA: "
+ + anchor.getSubjectX500Principal(),
+ ValidatorException.T_UNTRUSTED_CERT, anchor);
+ }
+ }
+ }
+
+ private SymantecTLSPolicy() {}
+}
diff -r a659ccd1888d -r ddbd9744a3d5 src/java.base/share/classes/sun/security/validator/Validator.java
--- a/src/java.base/share/classes/sun/security/validator/Validator.java Tue Dec 11 11:45:43 2018 +0530
+++ b/src/java.base/share/classes/sun/security/validator/Validator.java Wed Dec 12 15:04:47 2018 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -275,7 +275,8 @@
boolean checkUnresolvedCritExts =
(type == TYPE_PKIX) ? false : true;
endEntityChecker.check(chain[0], parameter,
- checkUnresolvedCritExts);
+ checkUnresolvedCritExts,
+ chain[chain.length-1]);
}
return chain;
diff -r a659ccd1888d -r ddbd9744a3d5 src/java.base/share/conf/security/java.security
--- a/src/java.base/share/conf/security/java.security Tue Dec 11 11:45:43 2018 +0530
+++ b/src/java.base/share/conf/security/java.security Wed Dec 12 15:04:47 2018 +0530
@@ -1088,3 +1088,26 @@
# the same name, with the same syntax and possible values.
#
#jdk.includeInExceptions=hostInfo,jar
+
+#
+# Policies for distrusting Certificate Authorities (CAs).
+#
+# This is a comma separated value of one or more case-sensitive strings, each
+# of which represents a policy for determining if a CA should be distrusted.
+# The supported values are:
+#
+# SYMANTEC_TLS : Distrust TLS Server certificates anchored by
+# a Symantec root CA and issued after April 16, 2019.
+#
+# Leading and trailing whitespace surrounding each value are ignored.
+# Unknown values are ignored. If the property is commented out or set to the
+# empty String, no policies are enforced.
+#
+# Note: This property is currently used by the JDK Reference implementation.
+# It is not guaranteed to be supported by other SE implementations. Also, this
+# property does not override other security properties which can restrict
+# certificates such as jdk.tls.disabledAlgorithms or
+# jdk.certpath.disabledAlgorithms; those restrictions are still enforced even
+# if this property is not enabled.
+#
+jdk.security.caDistrustPolicies=SYMANTEC_TLS
diff -r a659ccd1888d -r ddbd9744a3d5 src/java.base/unix/classes/java/lang/ProcessImpl.java
--- a/src/java.base/unix/classes/java/lang/ProcessImpl.java Tue Dec 11 11:45:43 2018 +0530
+++ b/src/java.base/unix/classes/java/lang/ProcessImpl.java Wed Dec 12 15:04:47 2018 +0530
@@ -412,7 +412,7 @@
new BufferedOutputStream(
new FileOutputStream(newFileDescriptor(fds[0])));
- stdout = (fds[1] == -1) ?
+ stdout = (fds[1] == -1 || forceNullOutputStream) ?
ProcessBuilder.NullInputStream.INSTANCE :
new BufferedInputStream(
stdout_inner_stream =
@@ -446,7 +446,7 @@
ProcessBuilder.NullOutputStream.INSTANCE :
new ProcessPipeOutputStream(fds[0]);
- stdout = (fds[1] == -1) ?
+ stdout = (fds[1] == -1 || forceNullOutputStream) ?
ProcessBuilder.NullInputStream.INSTANCE :
new DeferredCloseProcessPipeInputStream(fds[1]);
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiledClass.java
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiledClass.java Tue Dec 11 11:45:43 2018 +0530
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiledClass.java Wed Dec 12 15:04:47 2018 +0530
@@ -333,8 +333,7 @@
AOTKlassData data = klassData.get(name);
if (data != null) {
HotSpotResolvedObjectType oldType = data.getType();
- assert oldType == type : "duplicate classes for name " + type.getName() + ", fingerprints old: " + oldType.getFingerprint() + ", new: " + type.getFingerprint() +
- ", klass pointers old: " + oldType.klass() + ", new: " + type.klass();
+ assert oldType.equals(type) : "duplicate classes for name " + type.getName();
}
return data;
}
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Tue Dec 11 11:45:43 2018 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Wed Dec 12 15:04:47 2018 +0530
@@ -1121,7 +1121,7 @@
public void visitVarDef(JCVariableDecl tree) {
// Local variables have not been entered yet, so we need to do it now:
- if (env.info.scope.owner.kind == MTH) {
+ if (env.info.scope.owner.kind == MTH || env.info.scope.owner.kind == VAR) {
if (tree.sym != null) {
// parameters have already been entered
env.info.scope.enter(tree.sym);
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java Tue Dec 11 11:45:43 2018 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java Wed Dec 12 15:04:47 2018 +0530
@@ -1633,7 +1633,7 @@
protected boolean trackable(VarSymbol sym) {
return
sym.pos >= startPos &&
- ((sym.owner.kind == MTH ||
+ ((sym.owner.kind == MTH || sym.owner.kind == VAR ||
isFinalUninitializedField(sym)));
}
@@ -2009,7 +2009,7 @@
lint = lint.augment(tree.sym);
try{
boolean track = trackable(tree.sym);
- if (track && tree.sym.owner.kind == MTH) {
+ if (track && (tree.sym.owner.kind == MTH || tree.sym.owner.kind == VAR)) {
newVar(tree);
}
if (tree.init != null) {
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java Tue Dec 11 11:45:43 2018 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java Wed Dec 12 15:04:47 2018 +0530
@@ -25,8 +25,6 @@
package com.sun.tools.javac.jvm;
-import java.util.function.BiConsumer;
-
import com.sun.tools.javac.tree.TreeInfo.PosKind;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
@@ -166,6 +164,7 @@
boolean inCondSwitchExpression;
Chain switchExpressionTrueChain;
Chain switchExpressionFalseChain;
+ List stackBeforeSwitchExpression;
/** Generate code to load an integer constant.
* @param n The integer to be loaded.
@@ -1178,13 +1177,59 @@
}
private void doHandleSwitchExpression(JCSwitchExpression tree) {
- int prevLetExprStart = code.setLetExprStackPos(code.state.stacksize);
+ List prevStackBeforeSwitchExpression = stackBeforeSwitchExpression;
+ int limit = code.nextreg;
try {
- handleSwitch(tree, tree.selector, tree.cases);
+ stackBeforeSwitchExpression = List.nil();
+ if (hasTry(tree)) {
+ //if the switch expression contains try-catch, the catch handlers need to have
+ //an empty stack. So stash whole stack to local variables, and restore it before
+ //breaks:
+ while (code.state.stacksize > 0) {
+ Type type = code.state.peek();
+ Name varName = names.fromString(target.syntheticNameChar() +
+ "stack" +
+ target.syntheticNameChar() +
+ tree.pos +
+ target.syntheticNameChar() +
+ code.state.stacksize);
+ VarSymbol var = new VarSymbol(Flags.SYNTHETIC, varName, type,
+ this.env.enclMethod.sym);
+ LocalItem item = items.new LocalItem(type, code.newLocal(var));
+ stackBeforeSwitchExpression = stackBeforeSwitchExpression.prepend(item);
+ item.store();
+ }
+ }
+ int prevLetExprStart = code.setLetExprStackPos(code.state.stacksize);
+ try {
+ handleSwitch(tree, tree.selector, tree.cases);
+ } finally {
+ code.setLetExprStackPos(prevLetExprStart);
+ }
} finally {
- code.setLetExprStackPos(prevLetExprStart);
+ stackBeforeSwitchExpression = prevStackBeforeSwitchExpression;
+ code.endScopes(limit);
}
}
+ //where:
+ private boolean hasTry(JCSwitchExpression tree) {
+ boolean[] hasTry = new boolean[1];
+ new TreeScanner() {
+ @Override
+ public void visitTry(JCTry tree) {
+ hasTry[0] = true;
+ }
+
+ @Override
+ public void visitClassDef(JCClassDecl tree) {
+ }
+
+ @Override
+ public void visitLambda(JCLambda tree) {
+ }
+ }.scan(tree);
+ return hasTry[0];
+ }
private void handleSwitch(JCTree swtch, JCExpression selector, List cases) {
int limit = code.nextreg;
@@ -1659,14 +1704,17 @@
}
public void visitBreak(JCBreak tree) {
- int tmpPos = code.pendingStatPos;
Assert.check(code.isStatementStart());
- Env targetEnv = unwind(tree.target, env);
- code.pendingStatPos = tmpPos;
+ final Env targetEnv;
if (tree.isValueBreak()) {
+ //restore stack as it was before the switch expression:
+ for (LocalItem li : stackBeforeSwitchExpression) {
+ li.load();
+ }
if (inCondSwitchExpression) {
CondItem value = genCond(tree.value, CRT_FLOW_TARGET);
Chain falseJumps = value.jumpFalse();
+ targetEnv = unwindBreak(tree);
code.resolve(value.trueJumps);
Chain trueJumps = code.branch(goto_);
if (switchExpressionTrueChain == null) {
@@ -1684,13 +1732,22 @@
} else {
genExpr(tree.value, pt).load();
code.state.forceStackTop(tree.target.type);
+ targetEnv = unwindBreak(tree);
targetEnv.info.addExit(code.branch(goto_));
}
} else {
+ targetEnv = unwindBreak(tree);
targetEnv.info.addExit(code.branch(goto_));
}
endFinalizerGaps(env, targetEnv);
}
+ //where:
+ private Env unwindBreak(JCBreak tree) {
+ int tmpPos = code.pendingStatPos;
+ Env targetEnv = unwind(tree.target, env);
+ code.pendingStatPos = tmpPos;
+ return targetEnv;
+ }
public void visitContinue(JCContinue tree) {
int tmpPos = code.pendingStatPos;
@@ -2138,7 +2195,7 @@
res = items.makeMemberItem(sym, true);
}
result = res;
- } else if (sym.kind == VAR && sym.owner.kind == MTH) {
+ } else if (sym.kind == VAR && (sym.owner.kind == MTH || sym.owner.kind == VAR)) {
result = items.makeLocalItem((VarSymbol)sym);
} else if (isInvokeDynamic(sym)) {
result = items.makeDynamicItem(sym);
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.crypto.ec/share/classes/sun/security/ec/ECDHKeyAgreement.java
--- a/src/jdk.crypto.ec/share/classes/sun/security/ec/ECDHKeyAgreement.java Tue Dec 11 11:45:43 2018 +0530
+++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/ECDHKeyAgreement.java Wed Dec 12 15:04:47 2018 +0530
@@ -25,14 +25,19 @@
package sun.security.ec;
+import java.math.*;
import java.security.*;
import java.security.interfaces.*;
import java.security.spec.*;
+import java.util.Optional;
import javax.crypto.*;
import javax.crypto.spec.*;
+import sun.security.util.ArrayUtil;
import sun.security.util.ECUtil;
+import sun.security.util.math.*;
+import sun.security.ec.point.*;
/**
* KeyAgreement implementation for ECDH.
@@ -44,8 +49,8 @@
// private key, if initialized
private ECPrivateKey privateKey;
- // encoded public point, non-null between doPhase() & generateSecret() only
- private byte[] publicValue;
+ // public key, non-null between doPhase() & generateSecret() only
+ private ECPublicKey publicKey;
// length of the secret to be derived
private int secretLen;
@@ -65,7 +70,7 @@
("Key must be instance of PrivateKey");
}
privateKey = (ECPrivateKey) ECKeyFactory.toECKey(key);
- publicValue = null;
+ publicKey = null;
}
// see JCE spec
@@ -87,7 +92,7 @@
if (privateKey == null) {
throw new IllegalStateException("Not initialized");
}
- if (publicValue != null) {
+ if (publicKey != null) {
throw new IllegalStateException("Phase already executed");
}
if (!lastPhase) {
@@ -99,42 +104,74 @@
("Key must be a PublicKey with algorithm EC");
}
- ECPublicKey ecKey = (ECPublicKey)key;
- ECParameterSpec params = ecKey.getParams();
+ this.publicKey = (ECPublicKey) key;
- if (ecKey instanceof ECPublicKeyImpl) {
- publicValue = ((ECPublicKeyImpl)ecKey).getEncodedPublicValue();
- } else { // instanceof ECPublicKey
- publicValue =
- ECUtil.encodePoint(ecKey.getW(), params.getCurve());
- }
+ ECParameterSpec params = publicKey.getParams();
int keyLenBits = params.getCurve().getField().getFieldSize();
secretLen = (keyLenBits + 7) >> 3;
return null;
}
+ private static void validateCoordinate(BigInteger c, BigInteger mod) {
+ if (c.compareTo(BigInteger.ZERO) < 0) {
+ throw new ProviderException("invalid coordinate");
+ }
+
+ if (c.compareTo(mod) >= 0) {
+ throw new ProviderException("invalid coordinate");
+ }
+ }
+
+ /*
+ * Check whether a public key is valid. Throw ProviderException
+ * if it is not valid or could not be validated.
+ */
+ private static void validate(ECOperations ops, ECPublicKey key) {
+
+ // ensure that integers are in proper range
+ BigInteger x = key.getW().getAffineX();
+ BigInteger y = key.getW().getAffineY();
+
+ BigInteger p = ops.getField().getSize();
+ validateCoordinate(x, p);
+ validateCoordinate(y, p);
+
+ // ensure the point is on the curve
+ EllipticCurve curve = key.getParams().getCurve();
+ BigInteger rhs = x.modPow(BigInteger.valueOf(3), p).add(curve.getA()
+ .multiply(x)).add(curve.getB()).mod(p);
+ BigInteger lhs = y.modPow(BigInteger.valueOf(2), p).mod(p);
+ if (!rhs.equals(lhs)) {
+ throw new ProviderException("point is not on curve");
+ }
+
+ // check the order of the point
+ ImmutableIntegerModuloP xElem = ops.getField().getElement(x);
+ ImmutableIntegerModuloP yElem = ops.getField().getElement(y);
+ AffinePoint affP = new AffinePoint(xElem, yElem);
+ byte[] order = key.getParams().getOrder().toByteArray();
+ ArrayUtil.reverse(order);
+ Point product = ops.multiply(affP, order);
+ if (!ops.isNeutral(product)) {
+ throw new ProviderException("point has incorrect order");
+ }
+
+ }
+
// see JCE spec
@Override
protected byte[] engineGenerateSecret() throws IllegalStateException {
- if ((privateKey == null) || (publicValue == null)) {
+ if ((privateKey == null) || (publicKey == null)) {
throw new IllegalStateException("Not initialized correctly");
}
- byte[] s = privateKey.getS().toByteArray();
- byte[] encodedParams = // DER OID
- ECUtil.encodeECParameterSpec(null, privateKey.getParams());
-
- try {
-
- byte[] result = deriveKey(s, publicValue, encodedParams);
- publicValue = null;
- return result;
-
- } catch (GeneralSecurityException e) {
- throw new ProviderException("Could not derive key", e);
- }
-
+ Optional resultOpt = deriveKeyImpl(privateKey, publicKey);
+ byte[] result = resultOpt.orElseGet(
+ () -> deriveKeyNative(privateKey, publicKey)
+ );
+ publicKey = null;
+ return result;
}
// see JCE spec
@@ -143,7 +180,8 @@
offset) throws IllegalStateException, ShortBufferException {
if (offset + secretLen > sharedSecret.length) {
throw new ShortBufferException("Need " + secretLen
- + " bytes, only " + (sharedSecret.length - offset) + " available");
+ + " bytes, only " + (sharedSecret.length - offset)
+ + " available");
}
byte[] secret = engineGenerateSecret();
System.arraycopy(secret, 0, sharedSecret, offset, secret.length);
@@ -165,6 +203,78 @@
return new SecretKeySpec(engineGenerateSecret(), "TlsPremasterSecret");
}
+ private static
+ Optional deriveKeyImpl(ECPrivateKey priv, ECPublicKey pubKey) {
+
+ ECParameterSpec ecSpec = priv.getParams();
+ EllipticCurve curve = ecSpec.getCurve();
+ Optional opsOpt = ECOperations.forParameters(ecSpec);
+ if (opsOpt.isEmpty()) {
+ return Optional.empty();
+ }
+ ECOperations ops = opsOpt.get();
+ if (! (priv instanceof ECPrivateKeyImpl)) {
+ return Optional.empty();
+ }
+ ECPrivateKeyImpl privImpl = (ECPrivateKeyImpl) priv;
+ byte[] sArr = privImpl.getArrayS();
+
+ // to match the native implementation, validate the public key here
+ // and throw ProviderException if it is invalid
+ validate(ops, pubKey);
+
+ IntegerFieldModuloP field = ops.getField();
+ // convert s array into field element and multiply by the cofactor
+ MutableIntegerModuloP scalar = field.getElement(sArr).mutable();
+ SmallValue cofactor =
+ field.getSmallValue(priv.getParams().getCofactor());
+ scalar.setProduct(cofactor);
+ int keySize = (curve.getField().getFieldSize() + 7) / 8;
+ byte[] privArr = scalar.asByteArray(keySize);
+
+ ImmutableIntegerModuloP x =
+ field.getElement(pubKey.getW().getAffineX());
+ ImmutableIntegerModuloP y =
+ field.getElement(pubKey.getW().getAffineY());
+ AffinePoint affPub = new AffinePoint(x, y);
+ Point product = ops.multiply(affPub, privArr);
+ if (ops.isNeutral(product)) {
+ throw new ProviderException("Product is zero");
+ }
+ AffinePoint affProduct = product.asAffine();
+
+ byte[] result = affProduct.getX().asByteArray(keySize);
+ ArrayUtil.reverse(result);
+
+ return Optional.of(result);
+ }
+
+ private static
+ byte[] deriveKeyNative(ECPrivateKey privateKey, ECPublicKey publicKey) {
+
+ ECParameterSpec params = privateKey.getParams();
+ byte[] s = privateKey.getS().toByteArray();
+ byte[] encodedParams = // DER OID
+ ECUtil.encodeECParameterSpec(null, params);
+
+ byte[] publicValue;
+ if (publicKey instanceof ECPublicKeyImpl) {
+ ECPublicKeyImpl ecPub = (ECPublicKeyImpl) publicKey;
+ publicValue = ecPub.getEncodedPublicValue();
+ } else { // instanceof ECPublicKey
+ publicValue =
+ ECUtil.encodePoint(publicKey.getW(), params.getCurve());
+ }
+
+ try {
+ return deriveKey(s, publicValue, encodedParams);
+
+ } catch (GeneralSecurityException e) {
+ throw new ProviderException("Could not derive key", e);
+ }
+ }
+
+
/**
* Generates a secret key using the public and private keys.
*
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.crypto.ec/share/classes/sun/security/ec/ECDSAOperations.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/ECDSAOperations.java Wed Dec 12 15:04:47 2018 +0530
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.ec;
+
+import sun.security.ec.point.*;
+import sun.security.util.ArrayUtil;
+import sun.security.util.math.*;
+import static sun.security.ec.ECOperations.IntermediateValueException;
+
+import java.security.ProviderException;
+import java.security.spec.*;
+import java.util.Optional;
+
+public class ECDSAOperations {
+
+ public static class Seed {
+ private final byte[] seedValue;
+
+ public Seed(byte[] seedValue) {
+ this.seedValue = seedValue;
+ }
+
+ public byte[] getSeedValue() {
+ return seedValue;
+ }
+ }
+
+ public static class Nonce {
+ private final byte[] nonceValue;
+
+ public Nonce(byte[] nonceValue) {
+ this.nonceValue = nonceValue;
+ }
+
+ public byte[] getNonceValue() {
+ return nonceValue;
+ }
+ }
+
+ private final ECOperations ecOps;
+ private final AffinePoint basePoint;
+
+ public ECDSAOperations(ECOperations ecOps, ECPoint basePoint) {
+ this.ecOps = ecOps;
+ this.basePoint = toAffinePoint(basePoint, ecOps.getField());
+ }
+
+ public ECOperations getEcOperations() {
+ return ecOps;
+ }
+
+ public AffinePoint basePointMultiply(byte[] scalar) {
+ return ecOps.multiply(basePoint, scalar).asAffine();
+ }
+
+ public static AffinePoint toAffinePoint(ECPoint point,
+ IntegerFieldModuloP field) {
+
+ ImmutableIntegerModuloP affineX = field.getElement(point.getAffineX());
+ ImmutableIntegerModuloP affineY = field.getElement(point.getAffineY());
+ return new AffinePoint(affineX, affineY);
+ }
+
+ public static
+ Optional forParameters(ECParameterSpec ecParams) {
+ Optional curveOps =
+ ECOperations.forParameters(ecParams);
+ return curveOps.map(
+ ops -> new ECDSAOperations(ops, ecParams.getGenerator())
+ );
+ }
+
+ /**
+ *
+ * Sign a digest using the provided private key and seed.
+ * IMPORTANT: The private key is a scalar represented using a
+ * little-endian byte array. This is backwards from the conventional
+ * representation in ECDSA. The routines that produce and consume this
+ * value uses little-endian, so this deviation from convention removes
+ * the requirement to swap the byte order. The returned signature is in
+ * the conventional byte order.
+ *
+ * @param privateKey the private key scalar as a little-endian byte array
+ * @param digest the digest to be signed
+ * @param seed the seed that will be used to produce the nonce. This object
+ * should contain an array that is at least 64 bits longer than
+ * the number of bits required to represent the group order.
+ * @return the ECDSA signature value
+ * @throws IntermediateValueException if the signature cannot be produced
+ * due to an unacceptable intermediate or final value. If this
+ * exception is thrown, then the caller should discard the nonnce and
+ * try again with an entirely new nonce value.
+ */
+ public byte[] signDigest(byte[] privateKey, byte[] digest, Seed seed)
+ throws IntermediateValueException {
+
+ byte[] nonceArr = ecOps.seedToScalar(seed.getSeedValue());
+
+ Nonce nonce = new Nonce(nonceArr);
+ return signDigest(privateKey, digest, nonce);
+ }
+
+ /**
+ *
+ * Sign a digest using the provided private key and nonce.
+ * IMPORTANT: The private key and nonce are scalars represented by a
+ * little-endian byte array. This is backwards from the conventional
+ * representation in ECDSA. The routines that produce and consume these
+ * values use little-endian, so this deviation from convention removes
+ * the requirement to swap the byte order. The returned signature is in
+ * the conventional byte order.
+ *
+ * @param privateKey the private key scalar as a little-endian byte array
+ * @param digest the digest to be signed
+ * @param nonce the nonce object containing a little-endian scalar value.
+ * @return the ECDSA signature value
+ * @throws IntermediateValueException if the signature cannot be produced
+ * due to an unacceptable intermediate or final value. If this
+ * exception is thrown, then the caller should discard the nonnce and
+ * try again with an entirely new nonce value.
+ */
+ public byte[] signDigest(byte[] privateKey, byte[] digest, Nonce nonce)
+ throws IntermediateValueException {
+
+ IntegerFieldModuloP orderField = ecOps.getOrderField();
+ int orderBits = orderField.getSize().bitLength();
+ if (orderBits % 8 != 0 && orderBits < digest.length * 8) {
+ // This implementation does not support truncating digests to
+ // a length that is not a multiple of 8.
+ throw new ProviderException("Invalid digest length");
+ }
+
+ byte[] k = nonce.getNonceValue();
+ // check nonce length
+ int length = (orderField.getSize().bitLength() + 7) / 8;
+ if (k.length != length) {
+ throw new ProviderException("Incorrect nonce length");
+ }
+
+ MutablePoint R = ecOps.multiply(basePoint, k);
+ IntegerModuloP r = R.asAffine().getX();
+ // put r into the correct field by fully reducing to an array
+ byte[] temp = new byte[length];
+ r.asByteArray(temp);
+ r = orderField.getElement(temp);
+ // store r in result
+ r.asByteArray(temp);
+ byte[] result = new byte[2 * length];
+ ArrayUtil.reverse(temp);
+ System.arraycopy(temp, 0, result, 0, length);
+ // compare r to 0
+ if (ECOperations.allZero(temp)) {
+ throw new IntermediateValueException();
+ }
+
+ IntegerModuloP dU = orderField.getElement(privateKey);
+ int lengthE = Math.min(length, digest.length);
+ byte[] E = new byte[lengthE];
+ System.arraycopy(digest, 0, E, 0, lengthE);
+ ArrayUtil.reverse(E);
+ IntegerModuloP e = orderField.getElement(E);
+ IntegerModuloP kElem = orderField.getElement(k);
+ IntegerModuloP kInv = kElem.multiplicativeInverse();
+ MutableIntegerModuloP s = r.mutable();
+ s.setProduct(dU).setSum(e).setProduct(kInv);
+ // store s in result
+ s.asByteArray(temp);
+ ArrayUtil.reverse(temp);
+ System.arraycopy(temp, 0, result, length, length);
+ // compare s to 0
+ if (ECOperations.allZero(temp)) {
+ throw new IntermediateValueException();
+ }
+
+ return result;
+
+ }
+
+}
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.crypto.ec/share/classes/sun/security/ec/ECDSASignature.java
--- a/src/jdk.crypto.ec/share/classes/sun/security/ec/ECDSASignature.java Tue Dec 11 11:45:43 2018 +0530
+++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/ECDSASignature.java Wed Dec 12 15:04:47 2018 +0530
@@ -32,9 +32,11 @@
import java.security.*;
import java.security.interfaces.*;
import java.security.spec.*;
+import java.util.Optional;
import sun.security.jca.JCAUtil;
import sun.security.util.*;
+import static sun.security.ec.ECOperations.IntermediateValueException;
/**
* ECDSA signature implementation. This class currently supports the
@@ -147,7 +149,7 @@
// Stores the precomputed message digest value.
@Override
protected void engineUpdate(byte[] b, int off, int len)
- throws SignatureException {
+ throws SignatureException {
if (offset >= precomputedDigest.length) {
offset = RAW_ECDSA_MAX + 1;
return;
@@ -172,7 +174,7 @@
}
@Override
- protected void resetDigest(){
+ protected void resetDigest() {
offset = 0;
}
@@ -222,14 +224,14 @@
// Nested class for SHA224withECDSA signatures
public static final class SHA224 extends ECDSASignature {
public SHA224() {
- super("SHA-224");
+ super("SHA-224");
}
}
// Nested class for SHA224withECDSAinP1363Format signatures
public static final class SHA224inP1363Format extends ECDSASignature {
public SHA224inP1363Format() {
- super("SHA-224", true);
+ super("SHA-224", true);
}
}
@@ -278,7 +280,7 @@
// initialize for verification. See JCA doc
@Override
protected void engineInitVerify(PublicKey publicKey)
- throws InvalidKeyException {
+ throws InvalidKeyException {
this.publicKey = (ECPublicKey) ECKeyFactory.toECKey(publicKey);
// Should check that the supplied key is appropriate for signature
@@ -290,14 +292,14 @@
// initialize for signing. See JCA doc
@Override
protected void engineInitSign(PrivateKey privateKey)
- throws InvalidKeyException {
+ throws InvalidKeyException {
engineInitSign(privateKey, null);
}
// initialize for signing. See JCA doc
@Override
protected void engineInitSign(PrivateKey privateKey, SecureRandom random)
- throws InvalidKeyException {
+ throws InvalidKeyException {
this.privateKey = (ECPrivateKey) ECKeyFactory.toECKey(privateKey);
// Should check that the supplied key is appropriate for signature
@@ -337,7 +339,7 @@
// update the signature with the plaintext data. See JCA doc
@Override
protected void engineUpdate(byte[] b, int off, int len)
- throws SignatureException {
+ throws SignatureException {
messageDigest.update(b, off, len);
needsReset = true;
}
@@ -354,20 +356,67 @@
needsReset = true;
}
- // sign the data and return the signature. See JCA doc
- @Override
- protected byte[] engineSign() throws SignatureException {
+ private byte[] signDigestImpl(ECDSAOperations ops, int seedBits,
+ byte[] digest, ECPrivateKeyImpl privImpl, SecureRandom random)
+ throws SignatureException {
+
+ byte[] seedBytes = new byte[(seedBits + 7) / 8];
+ byte[] s = privImpl.getArrayS();
+
+ // Attempt to create the signature in a loop that uses new random input
+ // each time. The chance of failure is very small assuming the
+ // implementation derives the nonce using extra bits
+ int numAttempts = 128;
+ for (int i = 0; i < numAttempts; i++) {
+ random.nextBytes(seedBytes);
+ ECDSAOperations.Seed seed = new ECDSAOperations.Seed(seedBytes);
+ try {
+ return ops.signDigest(s, digest, seed);
+ } catch (IntermediateValueException ex) {
+ // try again in the next iteration
+ }
+ }
+
+ throw new SignatureException("Unable to produce signature after "
+ + numAttempts + " attempts");
+ }
+
+
+ private Optional signDigestImpl(ECPrivateKey privateKey,
+ byte[] digest, SecureRandom random) throws SignatureException {
+
+ if (! (privateKey instanceof ECPrivateKeyImpl)) {
+ return Optional.empty();
+ }
+ ECPrivateKeyImpl privImpl = (ECPrivateKeyImpl) privateKey;
+ ECParameterSpec params = privateKey.getParams();
+
+ // seed is the key size + 64 bits
+ int seedBits = params.getOrder().bitLength() + 64;
+ Optional opsOpt =
+ ECDSAOperations.forParameters(params);
+ if (opsOpt.isEmpty()) {
+ return Optional.empty();
+ } else {
+ byte[] sig = signDigestImpl(opsOpt.get(), seedBits, digest,
+ privImpl, random);
+ return Optional.of(sig);
+ }
+ }
+
+ private byte[] signDigestNative(ECPrivateKey privateKey, byte[] digest,
+ SecureRandom random) throws SignatureException {
+
byte[] s = privateKey.getS().toByteArray();
ECParameterSpec params = privateKey.getParams();
+
// DER OID
byte[] encodedParams = ECUtil.encodeECParameterSpec(null, params);
int keySize = params.getCurve().getField().getFieldSize();
// seed is twice the key size (in bytes) plus 1
byte[] seed = new byte[(((keySize + 7) >> 3) + 1) * 2];
- if (random == null) {
- random = JCAUtil.getSecureRandom();
- }
+
random.nextBytes(seed);
// random bits needed for timing countermeasures
@@ -375,14 +424,32 @@
// values must be non-zero to enable countermeasures
timingArgument |= 1;
- byte[] sig;
try {
- sig = signDigest(getDigestValue(), s, encodedParams, seed,
+ return signDigest(digest, s, encodedParams, seed,
timingArgument);
} catch (GeneralSecurityException e) {
throw new SignatureException("Could not sign data", e);
}
+ }
+
+ // sign the data and return the signature. See JCA doc
+ @Override
+ protected byte[] engineSign() throws SignatureException {
+
+ if (random == null) {
+ random = JCAUtil.getSecureRandom();
+ }
+
+ byte[] digest = getDigestValue();
+ Optional sigOpt = signDigestImpl(privateKey, digest, random);
+ byte[] sig;
+ if (sigOpt.isPresent()) {
+ sig = sigOpt.get();
+ } else {
+ sig = signDigestNative(privateKey, digest, random);
+ }
+
if (p1363Format) {
return sig;
} else {
@@ -400,7 +467,7 @@
byte[] encodedParams = ECUtil.encodeECParameterSpec(null, params);
if (publicKey instanceof ECPublicKeyImpl) {
- w = ((ECPublicKeyImpl)publicKey).getEncodedPublicValue();
+ w = ((ECPublicKeyImpl) publicKey).getEncodedPublicValue();
} else { // instanceof ECPublicKey
w = ECUtil.encodePoint(publicKey.getW(), params.getCurve());
}
@@ -423,13 +490,13 @@
@Override
@Deprecated
protected void engineSetParameter(String param, Object value)
- throws InvalidParameterException {
+ throws InvalidParameterException {
throw new UnsupportedOperationException("setParameter() not supported");
}
@Override
protected void engineSetParameter(AlgorithmParameterSpec params)
- throws InvalidAlgorithmParameterException {
+ throws InvalidAlgorithmParameterException {
if (params != null) {
throw new InvalidAlgorithmParameterException("No parameter accepted");
}
@@ -439,7 +506,7 @@
@Override
@Deprecated
protected Object engineGetParameter(String param)
- throws InvalidParameterException {
+ throws InvalidParameterException {
throw new UnsupportedOperationException("getParameter() not supported");
}
@@ -464,7 +531,7 @@
out.putInteger(r);
out.putInteger(s);
DerValue result =
- new DerValue(DerValue.tag_Sequence, out.toByteArray());
+ new DerValue(DerValue.tag_Sequence, out.toByteArray());
return result.toByteArray();
@@ -497,9 +564,9 @@
// r and s each occupy half the array
byte[] result = new byte[k << 1];
System.arraycopy(rBytes, 0, result, k - rBytes.length,
- rBytes.length);
+ rBytes.length);
System.arraycopy(sBytes, 0, result, result.length - sBytes.length,
- sBytes.length);
+ sBytes.length);
return result;
} catch (Exception e) {
@@ -539,13 +606,13 @@
* @return byte[] the signature.
*/
private static native byte[] signDigest(byte[] digest, byte[] s,
- byte[] encodedParams, byte[] seed, int timing)
- throws GeneralSecurityException;
+ byte[] encodedParams, byte[] seed, int timing)
+ throws GeneralSecurityException;
/**
* Verifies the signed digest using the public key.
*
- * @param signedDigest the signature to be verified. It is encoded
+ * @param signature the signature to be verified. It is encoded
* as a concatenation of the key's R and S values.
* @param digest the digest to be used.
* @param w the public key's W point (in uncompressed form).
@@ -554,6 +621,6 @@
* @return boolean true if the signature is successfully verified.
*/
private static native boolean verifySignedDigest(byte[] signature,
- byte[] digest, byte[] w, byte[] encodedParams)
- throws GeneralSecurityException;
+ byte[] digest, byte[] w, byte[] encodedParams)
+ throws GeneralSecurityException;
}
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.crypto.ec/share/classes/sun/security/ec/ECKeyPairGenerator.java
--- a/src/jdk.crypto.ec/share/classes/sun/security/ec/ECKeyPairGenerator.java Tue Dec 11 11:45:43 2018 +0530
+++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/ECKeyPairGenerator.java Wed Dec 12 15:04:47 2018 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -33,13 +33,15 @@
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
import java.security.spec.InvalidParameterSpecException;
+import java.security.spec.*;
+import java.util.Optional;
-import sun.security.ec.ECPrivateKeyImpl;
-import sun.security.ec.ECPublicKeyImpl;
import sun.security.jca.JCAUtil;
-import sun.security.util.ECParameters;
import sun.security.util.ECUtil;
+import sun.security.util.math.*;
+import sun.security.ec.point.*;
import static sun.security.util.SecurityProviderConstants.DEF_EC_KEY_SIZE;
+import static sun.security.ec.ECOperations.IntermediateValueException;
/**
* EC keypair generator.
@@ -90,14 +92,14 @@
ECParameterSpec ecSpec = null;
if (params instanceof ECParameterSpec) {
- ecSpec = ECUtil.getECParameterSpec(null,
- (ECParameterSpec)params);
+ ECParameterSpec ecParams = (ECParameterSpec) params;
+ ecSpec = ECUtil.getECParameterSpec(null, ecParams);
if (ecSpec == null) {
throw new InvalidAlgorithmParameterException(
"Unsupported curve: " + params);
}
} else if (params instanceof ECGenParameterSpec) {
- String name = ((ECGenParameterSpec)params).getName();
+ String name = ((ECGenParameterSpec) params).getName();
ecSpec = ECUtil.getECParameterSpec(null, name);
if (ecSpec == null) {
throw new InvalidAlgorithmParameterException(
@@ -112,8 +114,7 @@
ensureCurveIsSupported(ecSpec);
this.params = ecSpec;
- this.keySize =
- ((ECParameterSpec)this.params).getCurve().getField().getFieldSize();
+ this.keySize = ecSpec.getCurve().getField().getFieldSize();
this.random = random;
}
@@ -141,39 +142,97 @@
@Override
public KeyPair generateKeyPair() {
- byte[] encodedParams =
- ECUtil.encodeECParameterSpec(null, (ECParameterSpec)params);
-
- // seed is twice the key size (in bytes) plus 1
- byte[] seed = new byte[(((keySize + 7) >> 3) + 1) * 2];
if (random == null) {
random = JCAUtil.getSecureRandom();
}
- random.nextBytes(seed);
try {
-
- Object[] keyBytes = generateECKeyPair(keySize, encodedParams, seed);
+ Optional kp = generateKeyPairImpl(random);
+ if (kp.isPresent()) {
+ return kp.get();
+ }
+ return generateKeyPairNative(random);
+ } catch (Exception ex) {
+ throw new ProviderException(ex);
+ }
+ }
- // The 'params' object supplied above is equivalent to the native
- // one so there is no need to fetch it.
- // keyBytes[0] is the encoding of the native private key
- BigInteger s = new BigInteger(1, (byte[])keyBytes[0]);
+ private byte[] generatePrivateScalar(SecureRandom random,
+ ECOperations ecOps, int seedSize) {
+ // Attempt to create the private scalar in a loop that uses new random
+ // input each time. The chance of failure is very small assuming the
+ // implementation derives the nonce using extra bits
+ int numAttempts = 128;
+ byte[] seedArr = new byte[seedSize];
+ for (int i = 0; i < numAttempts; i++) {
+ random.nextBytes(seedArr);
+ try {
+ return ecOps.seedToScalar(seedArr);
+ } catch (IntermediateValueException ex) {
+ // try again in the next iteration
+ }
+ }
- PrivateKey privateKey =
- new ECPrivateKeyImpl(s, (ECParameterSpec)params);
+ throw new ProviderException("Unable to produce private key after "
+ + numAttempts + " attempts");
+ }
+
+ private Optional generateKeyPairImpl(SecureRandom random)
+ throws InvalidKeyException {
+
+ ECParameterSpec ecParams = (ECParameterSpec) params;
- // keyBytes[1] is the encoding of the native public key
- ECPoint w = ECUtil.decodePoint((byte[])keyBytes[1],
- ((ECParameterSpec)params).getCurve());
- PublicKey publicKey =
- new ECPublicKeyImpl(w, (ECParameterSpec)params);
+ Optional opsOpt = ECOperations.forParameters(ecParams);
+ if (opsOpt.isEmpty()) {
+ return Optional.empty();
+ }
+ ECOperations ops = opsOpt.get();
+ IntegerFieldModuloP field = ops.getField();
+ int numBits = ecParams.getOrder().bitLength();
+ int seedBits = numBits + 64;
+ int seedSize = (seedBits + 7) / 8;
+ byte[] privArr = generatePrivateScalar(random, ops, seedSize);
+
+ ECPoint genPoint = ecParams.getGenerator();
+ ImmutableIntegerModuloP x = field.getElement(genPoint.getAffineX());
+ ImmutableIntegerModuloP y = field.getElement(genPoint.getAffineY());
+ AffinePoint affGen = new AffinePoint(x, y);
+ Point pub = ops.multiply(affGen, privArr);
+ AffinePoint affPub = pub.asAffine();
+
+ PrivateKey privateKey = new ECPrivateKeyImpl(privArr, ecParams);
+
+ ECPoint w = new ECPoint(affPub.getX().asBigInteger(),
+ affPub.getY().asBigInteger());
+ PublicKey publicKey = new ECPublicKeyImpl(w, ecParams);
- return new KeyPair(publicKey, privateKey);
+ return Optional.of(new KeyPair(publicKey, privateKey));
+ }
+
+ private KeyPair generateKeyPairNative(SecureRandom random)
+ throws Exception {
+
+ ECParameterSpec ecParams = (ECParameterSpec) params;
+ byte[] encodedParams = ECUtil.encodeECParameterSpec(null, ecParams);
+
+ // seed is twice the key size (in bytes) plus 1
+ byte[] seed = new byte[(((keySize + 7) >> 3) + 1) * 2];
+ random.nextBytes(seed);
+ Object[] keyBytes = generateECKeyPair(keySize, encodedParams, seed);
- } catch (Exception e) {
- throw new ProviderException(e);
- }
+ // The 'params' object supplied above is equivalent to the native
+ // one so there is no need to fetch it.
+ // keyBytes[0] is the encoding of the native private key
+ BigInteger s = new BigInteger(1, (byte[]) keyBytes[0]);
+
+ PrivateKey privateKey = new ECPrivateKeyImpl(s, ecParams);
+
+ // keyBytes[1] is the encoding of the native public key
+ byte[] pubKey = (byte[]) keyBytes[1];
+ ECPoint w = ECUtil.decodePoint(pubKey, ecParams.getCurve());
+ PublicKey publicKey = new ECPublicKeyImpl(w, ecParams);
+
+ return new KeyPair(publicKey, privateKey);
}
private void checkKeySize(int keySize) throws InvalidParameterException {
@@ -190,7 +249,9 @@
/**
* Checks whether the curve in the encoded parameters is supported by the
- * native implementation.
+ * native implementation. Some curve operations will be performed by the
+ * Java implementation, but not all of them. So native support is still
+ * required for all curves.
*
* @param encodedParams encoded parameters in the same form accepted
* by generateECKeyPair
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.crypto.ec/share/classes/sun/security/ec/ECOperations.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/ECOperations.java Wed Dec 12 15:04:47 2018 +0530
@@ -0,0 +1,493 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.ec;
+
+import sun.security.ec.point.*;
+import sun.security.util.math.*;
+import sun.security.util.math.intpoly.*;
+
+import java.math.BigInteger;
+import java.security.ProviderException;
+import java.security.spec.ECFieldFp;
+import java.security.spec.ECParameterSpec;
+import java.security.spec.EllipticCurve;
+import java.util.Map;
+import java.util.Optional;
+
+/*
+ * Elliptic curve point arithmetic for prime-order curves where a=-3.
+ * Formulas are derived from "Complete addition formulas for prime order
+ * elliptic curves" by Renes, Costello, and Batina.
+ */
+
+public class ECOperations {
+
+ /*
+ * An exception indicating a problem with an intermediate value produced
+ * by some part of the computation. For example, the signing operation
+ * will throw this exception to indicate that the r or s value is 0, and
+ * that the signing operation should be tried again with a different nonce.
+ */
+ static class IntermediateValueException extends Exception {
+ private static final long serialVersionUID = 1;
+ }
+
+ static final Map fields = Map.of(
+ IntegerPolynomialP256.MODULUS, new IntegerPolynomialP256(),
+ IntegerPolynomialP384.MODULUS, new IntegerPolynomialP384(),
+ IntegerPolynomialP521.MODULUS, new IntegerPolynomialP521()
+ );
+
+ static final Map orderFields = Map.of(
+ P256OrderField.MODULUS, new P256OrderField(),
+ P384OrderField.MODULUS, new P384OrderField(),
+ P521OrderField.MODULUS, new P521OrderField()
+ );
+
+ public static Optional forParameters(ECParameterSpec params) {
+
+ EllipticCurve curve = params.getCurve();
+ if (!(curve.getField() instanceof ECFieldFp)) {
+ return Optional.empty();
+ }
+ ECFieldFp primeField = (ECFieldFp) curve.getField();
+
+ BigInteger three = BigInteger.valueOf(3);
+ if (!primeField.getP().subtract(curve.getA()).equals(three)) {
+ return Optional.empty();
+ }
+ IntegerFieldModuloP field = fields.get(primeField.getP());
+ if (field == null) {
+ return Optional.empty();
+ }
+
+ IntegerFieldModuloP orderField = orderFields.get(params.getOrder());
+ if (orderField == null) {
+ return Optional.empty();
+ }
+
+ ImmutableIntegerModuloP b = field.getElement(curve.getB());
+ ECOperations ecOps = new ECOperations(b, orderField);
+ return Optional.of(ecOps);
+ }
+
+ final ImmutableIntegerModuloP b;
+ final SmallValue one;
+ final SmallValue two;
+ final SmallValue three;
+ final SmallValue four;
+ final ProjectivePoint.Immutable neutral;
+ private final IntegerFieldModuloP orderField;
+
+ public ECOperations(IntegerModuloP b, IntegerFieldModuloP orderField) {
+ this.b = b.fixed();
+ this.orderField = orderField;
+
+ this.one = b.getField().getSmallValue(1);
+ this.two = b.getField().getSmallValue(2);
+ this.three = b.getField().getSmallValue(3);
+ this.four = b.getField().getSmallValue(4);
+
+ IntegerFieldModuloP field = b.getField();
+ this.neutral = new ProjectivePoint.Immutable(field.get0(),
+ field.get1(), field.get0());
+ }
+
+ public IntegerFieldModuloP getField() {
+ return b.getField();
+ }
+ public IntegerFieldModuloP getOrderField() {
+ return orderField;
+ }
+
+ protected ProjectivePoint.Immutable getNeutral() {
+ return neutral;
+ }
+
+ public boolean isNeutral(Point p) {
+ ProjectivePoint> pp = (ProjectivePoint>) p;
+
+ IntegerModuloP z = pp.getZ();
+
+ IntegerFieldModuloP field = z.getField();
+ int byteLength = (field.getSize().bitLength() + 7) / 8;
+ byte[] zBytes = z.asByteArray(byteLength);
+ return allZero(zBytes);
+ }
+
+ byte[] seedToScalar(byte[] seedBytes)
+ throws IntermediateValueException {
+
+ // Produce a nonce from the seed using FIPS 186-4,section B.5.1:
+ // Per-Message Secret Number Generation Using Extra Random Bits
+ // or
+ // Produce a scalar from the seed using FIPS 186-4, section B.4.1:
+ // Key Pair Generation Using Extra Random Bits
+
+ // To keep the implementation simple, sample in the range [0,n)
+ // and throw IntermediateValueException in the (unlikely) event
+ // that the result is 0.
+
+ // Get 64 extra bits and reduce in to the nonce
+ int seedBits = orderField.getSize().bitLength() + 64;
+ if (seedBytes.length * 8 < seedBits) {
+ throw new ProviderException("Incorrect seed length: " +
+ seedBytes.length * 8 + " < " + seedBits);
+ }
+
+ // input conversion only works on byte boundaries
+ // clear high-order bits of last byte so they don't influence nonce
+ int lastByteBits = seedBits % 8;
+ if (lastByteBits != 0) {
+ int lastByteIndex = seedBits / 8;
+ byte mask = (byte) (0xFF >>> (8 - lastByteBits));
+ seedBytes[lastByteIndex] &= mask;
+ }
+
+ int seedLength = (seedBits + 7) / 8;
+ IntegerModuloP scalarElem =
+ orderField.getElement(seedBytes, 0, seedLength, (byte) 0);
+ int scalarLength = (orderField.getSize().bitLength() + 7) / 8;
+ byte[] scalarArr = new byte[scalarLength];
+ scalarElem.asByteArray(scalarArr);
+ if (ECOperations.allZero(scalarArr)) {
+ throw new IntermediateValueException();
+ }
+ return scalarArr;
+ }
+
+ /*
+ * Compare all values in the array to 0 without branching on any value
+ *
+ */
+ public static boolean allZero(byte[] arr) {
+ byte acc = 0;
+ for (int i = 0; i < arr.length; i++) {
+ acc |= arr[i];
+ }
+ return acc == 0;
+ }
+
+ /*
+ * 4-bit branchless array lookup for projective points.
+ */
+ private void lookup4(ProjectivePoint.Immutable[] arr, int index,
+ ProjectivePoint.Mutable result, IntegerModuloP zero) {
+
+ for (int i = 0; i < 16; i++) {
+ int xor = index ^ i;
+ int bit3 = (xor & 0x8) >>> 3;
+ int bit2 = (xor & 0x4) >>> 2;
+ int bit1 = (xor & 0x2) >>> 1;
+ int bit0 = (xor & 0x1);
+ int inverse = bit0 | bit1 | bit2 | bit3;
+ int set = 1 - inverse;
+
+ ProjectivePoint.Immutable pi = arr[i];
+ result.conditionalSet(pi, set);
+ }
+ }
+
+ private void double4(ProjectivePoint.Mutable p, MutableIntegerModuloP t0,
+ MutableIntegerModuloP t1, MutableIntegerModuloP t2,
+ MutableIntegerModuloP t3, MutableIntegerModuloP t4) {
+
+ for (int i = 0; i < 4; i++) {
+ setDouble(p, t0, t1, t2, t3, t4);
+ }
+ }
+
+ /**
+ * Multiply an affine point by a scalar and return the result as a mutable
+ * point.
+ *
+ * @param affineP the point
+ * @param s the scalar as a little-endian array
+ * @return the product
+ */
+ public MutablePoint multiply(AffinePoint affineP, byte[] s) {
+
+ // 4-bit windowed multiply with branchless lookup.
+ // The mixed addition is faster, so it is used to construct the array
+ // at the beginning of the operation.
+
+ IntegerFieldModuloP field = affineP.getX().getField();
+ ImmutableIntegerModuloP zero = field.get0();
+ // temporaries
+ MutableIntegerModuloP t0 = zero.mutable();
+ MutableIntegerModuloP t1 = zero.mutable();
+ MutableIntegerModuloP t2 = zero.mutable();
+ MutableIntegerModuloP t3 = zero.mutable();
+ MutableIntegerModuloP t4 = zero.mutable();
+
+ ProjectivePoint.Mutable result = new ProjectivePoint.Mutable(field);
+ result.getY().setValue(field.get1().mutable());
+
+ ProjectivePoint.Immutable[] pointMultiples =
+ new ProjectivePoint.Immutable[16];
+ // 0P is neutral---same as initial result value
+ pointMultiples[0] = result.fixed();
+
+ ProjectivePoint.Mutable ps = new ProjectivePoint.Mutable(field);
+ ps.setValue(affineP);
+ // 1P = P
+ pointMultiples[1] = ps.fixed();
+
+ // the rest are calculated using mixed point addition
+ for (int i = 2; i < 16; i++) {
+ setSum(ps, affineP, t0, t1, t2, t3, t4);
+ pointMultiples[i] = ps.fixed();
+ }
+
+ ProjectivePoint.Mutable lookupResult = ps.mutable();
+
+ for (int i = s.length - 1; i >= 0; i--) {
+
+ double4(result, t0, t1, t2, t3, t4);
+
+ int high = (0xFF & s[i]) >>> 4;
+ lookup4(pointMultiples, high, lookupResult, zero);
+ setSum(result, lookupResult, t0, t1, t2, t3, t4);
+
+ double4(result, t0, t1, t2, t3, t4);
+
+ int low = 0xF & s[i];
+ lookup4(pointMultiples, low, lookupResult, zero);
+ setSum(result, lookupResult, t0, t1, t2, t3, t4);
+ }
+
+ return result;
+
+ }
+
+ /*
+ * Point double
+ */
+ private void setDouble(ProjectivePoint.Mutable p, MutableIntegerModuloP t0,
+ MutableIntegerModuloP t1, MutableIntegerModuloP t2,
+ MutableIntegerModuloP t3, MutableIntegerModuloP t4) {
+
+ t0.setValue(p.getX()).setSquare();
+ t1.setValue(p.getY()).setSquare();
+ t2.setValue(p.getZ()).setSquare();
+ t3.setValue(p.getX()).setProduct(p.getY());
+ t4.setValue(p.getY()).setProduct(p.getZ());
+
+ t3.setSum(t3);
+ p.getZ().setProduct(p.getX());
+
+ p.getZ().setProduct(two);
+
+ p.getY().setValue(t2).setProduct(b);
+ p.getY().setDifference(p.getZ());
+
+ p.getX().setValue(p.getY()).setProduct(two);
+ p.getY().setSum(p.getX());
+ p.getY().setReduced();
+ p.getX().setValue(t1).setDifference(p.getY());
+
+ p.getY().setSum(t1);
+ p.getY().setProduct(p.getX());
+ p.getX().setProduct(t3);
+
+ t3.setValue(t2).setProduct(two);
+ t2.setSum(t3);
+ p.getZ().setProduct(b);
+
+ t2.setReduced();
+ p.getZ().setDifference(t2);
+ p.getZ().setDifference(t0);
+ t3.setValue(p.getZ()).setProduct(two);
+ p.getZ().setReduced();
+ p.getZ().setSum(t3);
+ t0.setProduct(three);
+
+ t0.setDifference(t2);
+ t0.setProduct(p.getZ());
+ p.getY().setSum(t0);
+
+ t4.setSum(t4);
+ p.getZ().setProduct(t4);
+
+ p.getX().setDifference(p.getZ());
+ p.getZ().setValue(t4).setProduct(t1);
+
+ p.getZ().setProduct(four);
+
+ }
+
+ /*
+ * Mixed point addition. This method constructs new temporaries each time
+ * it is called. For better efficiency, the method that reuses temporaries
+ * should be used if more than one sum will be computed.
+ */
+ public void setSum(MutablePoint p, AffinePoint p2) {
+
+ IntegerModuloP zero = p.getField().get0();
+ MutableIntegerModuloP t0 = zero.mutable();
+ MutableIntegerModuloP t1 = zero.mutable();
+ MutableIntegerModuloP t2 = zero.mutable();
+ MutableIntegerModuloP t3 = zero.mutable();
+ MutableIntegerModuloP t4 = zero.mutable();
+ setSum((ProjectivePoint.Mutable) p, p2, t0, t1, t2, t3, t4);
+
+ }
+
+ /*
+ * Mixed point addition
+ */
+ private void setSum(ProjectivePoint.Mutable p, AffinePoint p2,
+ MutableIntegerModuloP t0, MutableIntegerModuloP t1,
+ MutableIntegerModuloP t2, MutableIntegerModuloP t3,
+ MutableIntegerModuloP t4) {
+
+ t0.setValue(p.getX()).setProduct(p2.getX());
+ t1.setValue(p.getY()).setProduct(p2.getY());
+ t3.setValue(p2.getX()).setSum(p2.getY());
+ t4.setValue(p.getX()).setSum(p.getY());
+ p.getX().setReduced();
+ t3.setProduct(t4);
+ t4.setValue(t0).setSum(t1);
+
+ t3.setDifference(t4);
+ t4.setValue(p2.getY()).setProduct(p.getZ());
+ t4.setSum(p.getY());
+
+ p.getY().setValue(p2.getX()).setProduct(p.getZ());
+ p.getY().setSum(p.getX());
+ t2.setValue(p.getZ());
+ p.getZ().setProduct(b);
+
+ p.getX().setValue(p.getY()).setDifference(p.getZ());
+ p.getX().setReduced();
+ p.getZ().setValue(p.getX()).setProduct(two);
+ p.getX().setSum(p.getZ());
+
+ p.getZ().setValue(t1).setDifference(p.getX());
+ p.getX().setSum(t1);
+ p.getY().setProduct(b);
+
+ t1.setValue(t2).setProduct(two);
+ t2.setSum(t1);
+ t2.setReduced();
+ p.getY().setDifference(t2);
+
+ p.getY().setDifference(t0);
+ p.getY().setReduced();
+ t1.setValue(p.getY()).setProduct(two);
+ p.getY().setSum(t1);
+
+ t1.setValue(t0).setProduct(two);
+ t0.setSum(t1);
+ t0.setDifference(t2);
+
+ t1.setValue(t4).setProduct(p.getY());
+ t2.setValue(t0).setProduct(p.getY());
+ p.getY().setValue(p.getX()).setProduct(p.getZ());
+
+ p.getY().setSum(t2);
+ p.getX().setProduct(t3);
+ p.getX().setDifference(t1);
+
+ p.getZ().setProduct(t4);
+ t1.setValue(t3).setProduct(t0);
+ p.getZ().setSum(t1);
+
+ }
+
+ /*
+ * Projective point addition
+ */
+ private void setSum(ProjectivePoint.Mutable p, ProjectivePoint.Mutable p2,
+ MutableIntegerModuloP t0, MutableIntegerModuloP t1,
+ MutableIntegerModuloP t2, MutableIntegerModuloP t3,
+ MutableIntegerModuloP t4) {
+
+ t0.setValue(p.getX()).setProduct(p2.getX());
+ t1.setValue(p.getY()).setProduct(p2.getY());
+ t2.setValue(p.getZ()).setProduct(p2.getZ());
+
+ t3.setValue(p.getX()).setSum(p.getY());
+ t4.setValue(p2.getX()).setSum(p2.getY());
+ t3.setProduct(t4);
+
+ t4.setValue(t0).setSum(t1);
+ t3.setDifference(t4);
+ t4.setValue(p.getY()).setSum(p.getZ());
+
+ p.getY().setValue(p2.getY()).setSum(p2.getZ());
+ t4.setProduct(p.getY());
+ p.getY().setValue(t1).setSum(t2);
+
+ t4.setDifference(p.getY());
+ p.getX().setSum(p.getZ());
+ p.getY().setValue(p2.getX()).setSum(p2.getZ());
+
+ p.getX().setProduct(p.getY());
+ p.getY().setValue(t0).setSum(t2);
+ p.getY().setAdditiveInverse().setSum(p.getX());
+ p.getY().setReduced();
+
+ p.getZ().setValue(t2).setProduct(b);
+ p.getX().setValue(p.getY()).setDifference(p.getZ());
+ p.getZ().setValue(p.getX()).setProduct(two);
+
+ p.getX().setSum(p.getZ());
+ p.getX().setReduced();
+ p.getZ().setValue(t1).setDifference(p.getX());
+ p.getX().setSum(t1);
+
+ p.getY().setProduct(b);
+ t1.setValue(t2).setSum(t2);
+ t2.setSum(t1);
+ t2.setReduced();
+
+ p.getY().setDifference(t2);
+ p.getY().setDifference(t0);
+ p.getY().setReduced();
+ t1.setValue(p.getY()).setSum(p.getY());
+
+ p.getY().setSum(t1);
+ t1.setValue(t0).setProduct(two);
+ t0.setSum(t1);
+
+ t0.setDifference(t2);
+ t1.setValue(t4).setProduct(p.getY());
+ t2.setValue(t0).setProduct(p.getY());
+
+ p.getY().setValue(p.getX()).setProduct(p.getZ());
+ p.getY().setSum(t2);
+ p.getX().setProduct(t3);
+
+ p.getX().setDifference(t1);
+ p.getZ().setProduct(t4);
+ t1.setValue(t3).setProduct(t0);
+
+ p.getZ().setSum(t1);
+
+ }
+}
+
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.crypto.ec/share/classes/sun/security/ec/ECPrivateKeyImpl.java
--- a/src/jdk.crypto.ec/share/classes/sun/security/ec/ECPrivateKeyImpl.java Tue Dec 11 11:45:43 2018 +0530
+++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/ECPrivateKeyImpl.java Wed Dec 12 15:04:47 2018 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -32,11 +32,7 @@
import java.security.interfaces.*;
import java.security.spec.*;
-import sun.security.util.DerInputStream;
-import sun.security.util.DerOutputStream;
-import sun.security.util.DerValue;
-import sun.security.util.ECParameters;
-import sun.security.util.ECUtil;
+import sun.security.util.*;
import sun.security.x509.AlgorithmId;
import sun.security.pkcs.PKCS8Key;
@@ -68,6 +64,7 @@
private static final long serialVersionUID = 88695385615075129L;
private BigInteger s; // private value
+ private byte[] arrayS; // private value as a little-endian array
private ECParameterSpec params;
/**
@@ -85,13 +82,25 @@
throws InvalidKeyException {
this.s = s;
this.params = params;
- // generate the encoding
+ makeEncoding(s);
+
+ }
+
+ ECPrivateKeyImpl(byte[] s, ECParameterSpec params)
+ throws InvalidKeyException {
+ this.arrayS = s.clone();
+ this.params = params;
+ makeEncoding(s);
+ }
+
+ private void makeEncoding(byte[] s) throws InvalidKeyException {
algid = new AlgorithmId
- (AlgorithmId.EC_oid, ECParameters.getAlgorithmParameters(params));
+ (AlgorithmId.EC_oid, ECParameters.getAlgorithmParameters(params));
try {
DerOutputStream out = new DerOutputStream();
out.putInteger(1); // version 1
- byte[] privBytes = ECUtil.trimZeroes(s.toByteArray());
+ byte[] privBytes = s.clone();
+ ArrayUtil.reverse(privBytes);
out.putOctetString(privBytes);
DerValue val =
new DerValue(DerValue.tag_Sequence, out.toByteArray());
@@ -102,6 +111,31 @@
}
}
+ private void makeEncoding(BigInteger s) throws InvalidKeyException {
+ algid = new AlgorithmId
+ (AlgorithmId.EC_oid, ECParameters.getAlgorithmParameters(params));
+ try {
+ byte[] sArr = s.toByteArray();
+ // convert to fixed-length array
+ int numOctets = (params.getOrder().bitLength() + 7) / 8;
+ byte[] sOctets = new byte[numOctets];
+ int inPos = Math.max(sArr.length - sOctets.length, 0);
+ int outPos = Math.max(sOctets.length - sArr.length, 0);
+ int length = Math.min(sArr.length, sOctets.length);
+ System.arraycopy(sArr, inPos, sOctets, outPos, length);
+
+ DerOutputStream out = new DerOutputStream();
+ out.putInteger(1); // version 1
+ out.putOctetString(sOctets);
+ DerValue val =
+ new DerValue(DerValue.tag_Sequence, out.toByteArray());
+ key = val.toByteArray();
+ } catch (IOException exc) {
+ // should never occur
+ throw new InvalidKeyException(exc);
+ }
+ }
+
// see JCA doc
public String getAlgorithm() {
return "EC";
@@ -109,9 +143,26 @@
// see JCA doc
public BigInteger getS() {
+ if (s == null) {
+ byte[] arrCopy = arrayS.clone();
+ ArrayUtil.reverse(arrCopy);
+ s = new BigInteger(1, arrCopy);
+ }
return s;
}
+ public byte[] getArrayS() {
+ if (arrayS == null) {
+ byte[] arr = getS().toByteArray();
+ ArrayUtil.reverse(arr);
+ int byteLength = (params.getOrder().bitLength() + 7) / 8;
+ arrayS = new byte[byteLength];
+ int length = Math.min(byteLength, arr.length);
+ System.arraycopy(arr, 0, arrayS, 0, length);
+ }
+ return arrayS.clone();
+ }
+
// see JCA doc
public ECParameterSpec getParams() {
return params;
@@ -133,12 +184,13 @@
throw new IOException("Version must be 1");
}
byte[] privData = data.getOctetString();
- s = new BigInteger(1, privData);
+ ArrayUtil.reverse(privData);
+ arrayS = privData;
while (data.available() != 0) {
DerValue value = data.getDerValue();
- if (value.isContextSpecific((byte)0)) {
+ if (value.isContextSpecific((byte) 0)) {
// ignore for now
- } else if (value.isContextSpecific((byte)1)) {
+ } else if (value.isContextSpecific((byte) 1)) {
// ignore for now
} else {
throw new InvalidKeyException("Unexpected value: " + value);
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.crypto.ec/share/classes/sun/security/ec/point/AffinePoint.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/point/AffinePoint.java Wed Dec 12 15:04:47 2018 +0530
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package sun.security.ec.point;
+
+import sun.security.util.math.ImmutableIntegerModuloP;
+
+import java.util.Objects;
+
+/**
+ * Elliptic curve point represented using affine coordinates (x, y). This class
+ * is not part of the sun.security.ec.point.Point hierarchy because it is not
+ * used to hold intermediate values during point arithmetic, and so it does not
+ * have a mutable form.
+ */
+public class AffinePoint {
+
+ private final ImmutableIntegerModuloP x;
+ private final ImmutableIntegerModuloP y;
+
+ public AffinePoint(ImmutableIntegerModuloP x, ImmutableIntegerModuloP y) {
+ this.x = x;
+ this.y = y;
+ }
+
+ public ImmutableIntegerModuloP getX() {
+ return x;
+ }
+
+ public ImmutableIntegerModuloP getY() {
+ return y;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof AffinePoint)) {
+ return false;
+ }
+ AffinePoint p = (AffinePoint) obj;
+ boolean xEquals = x.asBigInteger().equals(p.x.asBigInteger());
+ boolean yEquals = y.asBigInteger().equals(p.y.asBigInteger());
+ return xEquals && yEquals;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(x, y);
+ }
+
+ @Override
+ public String toString() {
+ return "(" + x.asBigInteger().toString() + "," +
+ y.asBigInteger().toString() + ")";
+ }
+}
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.crypto.ec/share/classes/sun/security/ec/point/ImmutablePoint.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/point/ImmutablePoint.java Wed Dec 12 15:04:47 2018 +0530
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.ec.point;
+
+/**
+ * An interface for immutable points on an elliptic curve over a finite field.
+ */
+public interface ImmutablePoint extends Point {
+}
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.crypto.ec/share/classes/sun/security/ec/point/MutablePoint.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/point/MutablePoint.java Wed Dec 12 15:04:47 2018 +0530
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.ec.point;
+
+/**
+ * An interface for mutable points on an elliptic curve over a finite field.
+ */
+public interface MutablePoint extends Point {
+
+ MutablePoint setValue(AffinePoint p);
+ MutablePoint setValue(Point p);
+ MutablePoint conditionalSet(Point p, int set);
+
+}
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.crypto.ec/share/classes/sun/security/ec/point/Point.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/point/Point.java Wed Dec 12 15:04:47 2018 +0530
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.ec.point;
+
+import sun.security.util.math.IntegerFieldModuloP;
+
+/**
+ * A base interface for points on an elliptic curve over a finite field.
+ * Implementations may use different representations for points, and this
+ * interface creates a common API for manipulating points. This API has no
+ * methods for point arithmetic, which depends on group structure and curve
+ * parameters in addition to point representation.
+ */
+public interface Point {
+
+ IntegerFieldModuloP getField();
+ AffinePoint asAffine();
+
+ ImmutablePoint fixed();
+ MutablePoint mutable();
+
+}
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.crypto.ec/share/classes/sun/security/ec/point/ProjectivePoint.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/point/ProjectivePoint.java Wed Dec 12 15:04:47 2018 +0530
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package sun.security.ec.point;
+
+import sun.security.util.math.*;
+
+/**
+ * Elliptic curve point in projective coordinates (X, Y, Z) where
+ * an affine point (x, y) is represented using any (X, Y, Z) s.t.
+ * x = X/Z and y = Y/Z.
+ */
+public abstract class ProjectivePoint
+ implements Point {
+
+ protected final T x;
+ protected final T y;
+ protected final T z;
+
+ protected ProjectivePoint(T x, T y, T z) {
+
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ @Override
+ public IntegerFieldModuloP getField() {
+ return this.x.getField();
+ }
+
+ @Override
+ public Immutable fixed() {
+ return new Immutable(x.fixed(), y.fixed(), z.fixed());
+ }
+
+ @Override
+ public Mutable mutable() {
+ return new Mutable(x.mutable(), y.mutable(), z.mutable());
+ }
+
+ public T getX() {
+ return x;
+ }
+
+ public T getY() {
+ return y;
+ }
+
+ public T getZ() {
+ return z;
+ }
+
+ public AffinePoint asAffine() {
+ IntegerModuloP zInv = z.multiplicativeInverse();
+ return new AffinePoint(x.multiply(zInv), y.multiply(zInv));
+ }
+
+ public static class Immutable
+ extends ProjectivePoint
+ implements ImmutablePoint {
+
+ public Immutable(ImmutableIntegerModuloP x,
+ ImmutableIntegerModuloP y,
+ ImmutableIntegerModuloP z) {
+ super(x, y, z);
+ }
+ }
+
+ public static class Mutable
+ extends ProjectivePoint
+ implements MutablePoint {
+
+ public Mutable(MutableIntegerModuloP x,
+ MutableIntegerModuloP y,
+ MutableIntegerModuloP z) {
+ super(x, y, z);
+ }
+
+ public Mutable(IntegerFieldModuloP field) {
+ super(field.get0().mutable(),
+ field.get0().mutable(),
+ field.get0().mutable());
+ }
+
+ @Override
+ public Mutable conditionalSet(Point p, int set) {
+ if (!(p instanceof ProjectivePoint)) {
+ throw new RuntimeException("Incompatible point");
+ }
+ @SuppressWarnings("unchecked")
+ ProjectivePoint pp =
+ (ProjectivePoint) p;
+ return conditionalSet(pp, set);
+ }
+
+ private
+ Mutable conditionalSet(ProjectivePoint pp, int set) {
+
+ x.conditionalSet(pp.x, set);
+ y.conditionalSet(pp.y, set);
+ z.conditionalSet(pp.z, set);
+
+ return this;
+ }
+
+ @Override
+ public Mutable setValue(AffinePoint p) {
+ x.setValue(p.getX());
+ y.setValue(p.getY());
+ z.setValue(p.getX().getField().get1());
+
+ return this;
+ }
+
+ @Override
+ public Mutable setValue(Point p) {
+ if (!(p instanceof ProjectivePoint)) {
+ throw new RuntimeException("Incompatible point");
+ }
+ @SuppressWarnings("unchecked")
+ ProjectivePoint pp =
+ (ProjectivePoint) p;
+ return setValue(pp);
+ }
+
+ private
+ Mutable setValue(ProjectivePoint pp) {
+
+ x.setValue(pp.x);
+ y.setValue(pp.y);
+ z.setValue(pp.z);
+
+ return this;
+ }
+
+ }
+
+}
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.internal.le/share/classes/jdk/internal/jline/DefaultTerminal2.java
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/DefaultTerminal2.java Tue Dec 11 11:45:43 2018 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,135 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import jdk.internal.jline.internal.InfoCmp;
-
-/**
- * Terminal wrapper with default ansi capabilities
- */
-public class DefaultTerminal2 implements Terminal2 {
-
- private final Terminal terminal;
- private final Set bools = new HashSet();
- private final Map strings = new HashMap();
-
- public DefaultTerminal2(Terminal terminal) {
- this.terminal = terminal;
- registerCap("key_backspace", "^H");
- registerCap("bell", "^G");
- registerCap("carriage_return", "^M");
- if (true/*isSupported() && isAnsiSupported()*/) {
- registerCap("clr_eol", "\\E[K");
- registerCap("clr_bol", "\\E[1K");
- registerCap("cursor_up", "\\E[A");
- registerCap("cursor_down", "^J");
- registerCap("column_address", "\\E[%i%p1%dG");
- registerCap("clear_screen", "\\E[H\\E[2J");
- registerCap("parm_down_cursor", "\\E[%p1%dB");
- registerCap("cursor_left", "^H");
- registerCap("cursor_right", "\\E[C");
- }
- if (hasWeirdWrap()) {
- registerCap("eat_newline_glitch");
- registerCap("auto_right_margin");
- }
- }
-
- public void init() throws Exception {
- terminal.init();
- }
-
- public void restore() throws Exception {
- terminal.restore();
- }
-
- public void reset() throws Exception {
- terminal.reset();
- }
-
- public boolean isSupported() {
- return terminal.isSupported();
- }
-
- public int getWidth() {
- return terminal.getWidth();
- }
-
- public int getHeight() {
- return terminal.getHeight();
- }
-
- public boolean isAnsiSupported() {
- return terminal.isAnsiSupported();
- }
-
- public OutputStream wrapOutIfNeeded(OutputStream out) {
- return terminal.wrapOutIfNeeded(out);
- }
-
- public InputStream wrapInIfNeeded(InputStream in) throws IOException {
- return terminal.wrapInIfNeeded(in);
- }
-
- public boolean hasWeirdWrap() {
- return terminal.hasWeirdWrap();
- }
-
- public boolean isEchoEnabled() {
- return terminal.isEchoEnabled();
- }
-
- public void setEchoEnabled(boolean enabled) {
- terminal.setEchoEnabled(enabled);
- }
-
- public void disableInterruptCharacter() {
- terminal.disableInterruptCharacter();
- }
-
- public void enableInterruptCharacter() {
- terminal.enableInterruptCharacter();
- }
-
- public String getOutputEncoding() {
- return terminal.getOutputEncoding();
- }
-
- private void registerCap(String cap, String value) {
- for (String key : InfoCmp.getNames(cap)) {
- strings.put(key, value);
- }
- }
-
- private void registerCap(String cap) {
- Collections.addAll(bools, InfoCmp.getNames(cap));
- }
-
- public boolean getBooleanCapability(String capability) {
- return bools.contains(capability);
- }
-
- public Integer getNumericCapability(String capability) {
- return null;
- }
-
- public String getStringCapability(String capability) {
- return strings.get(capability);
- }
-
-}
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.internal.le/share/classes/jdk/internal/jline/NoInterruptUnixTerminal.java
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/NoInterruptUnixTerminal.java Tue Dec 11 11:45:43 2018 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline;
-
-// Based on Apache Karaf impl
-
-/**
- * Non-interruptible (via CTRL-C) {@link UnixTerminal}.
- *
- * @since 2.0
- */
-public class NoInterruptUnixTerminal
- extends UnixTerminal
-{
- private String intr;
-
- public NoInterruptUnixTerminal() throws Exception {
- super();
- }
-
- @Override
- public void init() throws Exception {
- super.init();
- intr = getSettings().getPropertyAsString("intr");
- if ("".equals(intr)) {
- intr = null;
- }
- if (intr != null) {
- getSettings().undef("intr");
- }
- }
-
- @Override
- public void restore() throws Exception {
- if (intr != null) {
- getSettings().set("intr", intr);
- }
- super.restore();
- }
-}
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.internal.le/share/classes/jdk/internal/jline/OSvTerminal.java
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/OSvTerminal.java Tue Dec 11 11:45:43 2018 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline;
-
-import jdk.internal.jline.internal.Log;
-
-/**
- * Terminal that is used for OSv. This is seperate to unix terminal
- * implementation because exec cannot be used as currently used by UnixTerminal.
- *
- * This implimentation is derrived from the implementation at
- * https://github.com/cloudius-systems/mgmt/blob/master/crash/src/main/java/com/cloudius/cli/OSvTerminal.java
- * authored by Or Cohen.
- *
- * @author Or Cohen
- * @author Arun Neelicattu
- * @since 2.13
- */
-public class OSvTerminal
- extends TerminalSupport
-{
-
- public Class> sttyClass = null;
- public Object stty = null;
-
- @SuppressWarnings("deprecation")
- public OSvTerminal() {
- super(true);
-
- setAnsiSupported(true);
-
- try {
- if (stty == null) {
- sttyClass = Class.forName("com.cloudius.util.Stty");
- stty = sttyClass.newInstance();
- }
- } catch (Exception e) {
- Log.warn("Failed to load com.cloudius.util.Stty", e);
- }
- }
-
- @Override
- public void init() throws Exception {
- super.init();
-
- if (stty != null) {
- sttyClass.getMethod("jlineMode").invoke(stty);
- }
- }
-
- @Override
- public void restore() throws Exception {
- if (stty != null) {
- sttyClass.getMethod("reset").invoke(stty);
- }
- super.restore();
-
- // Newline in end of restore like in jline.UnixTerminal
- System.out.println();
- }
-
-}
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.internal.le/share/classes/jdk/internal/jline/Terminal.java
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/Terminal.java Tue Dec 11 11:45:43 2018 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-/**
- * Representation of the input terminal for a platform.
- *
- * @author Marc Prud'hommeaux
- * @author Jason Dillon
- * @since 2.0
- */
-public interface Terminal
-{
- void init() throws Exception;
-
- void restore() throws Exception;
-
- void reset() throws Exception;
-
- boolean isSupported();
-
- int getWidth();
-
- int getHeight();
-
- boolean isAnsiSupported();
-
- /**
- * When ANSI is not natively handled, the output will have to be wrapped.
- */
- OutputStream wrapOutIfNeeded(OutputStream out);
-
- /**
- * When using native support, return the InputStream to use for reading characters
- * else return the input stream passed as a parameter.
- *
- * @since 2.6
- */
- InputStream wrapInIfNeeded(InputStream in) throws IOException;
-
- /**
- * For terminals that don't wrap when character is written in last column,
- * only when the next character is written.
- * These are the ones that have 'am' and 'xn' termcap attributes (xterm and
- * rxvt flavors falls under that category)
- */
- boolean hasWeirdWrap();
-
- boolean isEchoEnabled();
-
- void setEchoEnabled(boolean enabled);
-
- void disableInterruptCharacter();
- void enableInterruptCharacter();
-
- String getOutputEncoding();
-
-}
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.internal.le/share/classes/jdk/internal/jline/Terminal2.java
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/Terminal2.java Tue Dec 11 11:45:43 2018 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline;
-
-/**
- * Terminal extension.
- *
- * @author Guillaume Nodet
- * @since 2.13
- */
-public interface Terminal2 extends Terminal
-{
- boolean getBooleanCapability(String capability);
-
- Integer getNumericCapability(String capability);
-
- String getStringCapability(String capability);
-
-}
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.internal.le/share/classes/jdk/internal/jline/TerminalFactory.java
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/TerminalFactory.java Tue Dec 11 11:45:43 2018 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,211 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline;
-
-import java.text.MessageFormat;
-import java.util.HashMap;
-import java.util.Map;
-
-import jdk.internal.jline.internal.Configuration;
-import jdk.internal.jline.internal.Log;
-import static jdk.internal.jline.internal.Preconditions.checkNotNull;
-
-/**
- * Creates terminal instances.
- *
- * @author Jason Dillon
- * @since 2.0
- */
-public class TerminalFactory
-{
- public static final String JLINE_TERMINAL = "jline.terminal";
-
- public static final String AUTO = "auto";
-
- public static final String UNIX = "unix";
-
- public static final String OSV = "osv";
-
- public static final String WIN = "win";
-
- public static final String WINDOWS = "windows";
-
- public static final String FREEBSD = "freebsd";
-
- public static final String NONE = "none";
-
- public static final String OFF = "off";
-
- public static final String FALSE = "false";
-
- private static Terminal term = null;
-
- public static synchronized Terminal create() {
- return create(null);
- }
-
- public static synchronized Terminal create(String ttyDevice) {
- if (Log.TRACE) {
- //noinspection ThrowableInstanceNeverThrown
- Log.trace(new Throwable("CREATE MARKER"));
- }
-
- String defaultType = "dumb".equals(System.getenv("TERM")) ? NONE : AUTO;
- String type = Configuration.getString(JLINE_TERMINAL, defaultType);
-
- Log.debug("Creating terminal; type=", type);
-
- Terminal t;
- try {
- String tmp = type.toLowerCase();
-
- if (tmp.equals(UNIX)) {
- t = getFlavor(Flavor.UNIX);
- }
- else if (tmp.equals(OSV)) {
- t = getFlavor(Flavor.OSV);
- }
- else if (tmp.equals(WIN) || tmp.equals(WINDOWS)) {
- t = getFlavor(Flavor.WINDOWS);
- }
- else if (tmp.equals(NONE) || tmp.equals(OFF) || tmp.equals(FALSE)) {
- if (System.getenv("INSIDE_EMACS") != null) {
- // emacs requires ansi on and echo off
- t = new UnsupportedTerminal(true, false);
- } else {
- // others the other way round
- t = new UnsupportedTerminal(false, true);
- }
- }
- else {
- if (tmp.equals(AUTO)) {
- String os = Configuration.getOsName();
- Flavor flavor = Flavor.UNIX;
- if (os.contains(WINDOWS)) {
- flavor = Flavor.WINDOWS;
- } else if (System.getenv("OSV_CPUS") != null) {
- flavor = Flavor.OSV;
- }
- t = getFlavor(flavor, ttyDevice);
- }
- else {
- try {
- @SuppressWarnings("deprecation")
- Object o = Thread.currentThread().getContextClassLoader().loadClass(type).newInstance();
- t = (Terminal) o;
- }
- catch (Exception e) {
- throw new IllegalArgumentException(MessageFormat.format("Invalid terminal type: {0}", type), e);
- }
- }
- }
- }
- catch (Exception e) {
- Log.error("Failed to construct terminal; falling back to unsupported", e);
- t = new UnsupportedTerminal();
- }
-
- Log.debug("Created Terminal: ", t);
-
- try {
- t.init();
- }
- catch (Throwable e) {
- Log.error("Terminal initialization failed; falling back to unsupported", e);
- return new UnsupportedTerminal();
- }
-
- return t;
- }
-
- public static synchronized void reset() {
- term = null;
- }
-
- public static synchronized void resetIf(final Terminal t) {
- if(t == term) {
- reset();
- }
- }
-
- public static enum Type
- {
- AUTO,
- WINDOWS,
- UNIX,
- OSV,
- NONE
- }
-
- public static synchronized void configure(final String type) {
- checkNotNull(type);
- System.setProperty(JLINE_TERMINAL, type);
- }
-
- public static synchronized void configure(final Type type) {
- checkNotNull(type);
- configure(type.name().toLowerCase());
- }
-
- //
- // Flavor Support
- //
-
- public static enum Flavor
- {
- WINDOWS,
- UNIX,
- OSV
- }
-
- private static final Map FLAVORS = new HashMap<>();
-
- static {
- registerFlavor(Flavor.WINDOWS, ttyDevice -> new WindowsTerminal());
- registerFlavor(Flavor.UNIX, ttyDevice -> new UnixTerminal(ttyDevice));
- registerFlavor(Flavor.OSV, ttyDevice -> new OSvTerminal());
- }
-
- public static synchronized Terminal get(String ttyDevice) {
- // The code is assuming we've got only one terminal per process.
- // Continuing this assumption, if this terminal is already initialized,
- // we don't check if it's using the same tty line either. Both assumptions
- // are a bit crude. TODO: check single terminal assumption.
- if (term == null) {
- term = create(ttyDevice);
- }
- return term;
- }
-
- public static synchronized Terminal get() {
- return get(null);
- }
-
- public static Terminal getFlavor(final Flavor flavor) throws Exception {
- return getFlavor(flavor, null);
- }
-
- @SuppressWarnings("deprecation")
- public static Terminal getFlavor(final Flavor flavor, String ttyDevice) throws Exception {
- TerminalConstructor factory = FLAVORS.get(flavor);
- if (factory != null) {
- return factory.createTerminal(ttyDevice);
- } else {
- throw new InternalError();
- }
- }
-
- public static void registerFlavor(final Flavor flavor, final TerminalConstructor factory) {
- FLAVORS.put(flavor, factory);
- }
-
- public interface TerminalConstructor {
- public Terminal createTerminal(String str) throws Exception;
- }
-}
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.internal.le/share/classes/jdk/internal/jline/TerminalSupport.java
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/TerminalSupport.java Tue Dec 11 11:45:43 2018 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,129 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import jdk.internal.jline.internal.Log;
-import jdk.internal.jline.internal.ShutdownHooks;
-import jdk.internal.jline.internal.ShutdownHooks.Task;
-
-/**
- * Provides support for {@link Terminal} instances.
- *
- * @author Jason Dillon
- * @since 2.0
- */
-public abstract class TerminalSupport
- implements Terminal
-{
- public static final int DEFAULT_WIDTH = 80;
-
- public static final int DEFAULT_HEIGHT = 24;
-
- private Task shutdownTask;
-
- private boolean supported;
-
- private boolean echoEnabled;
-
- private boolean ansiSupported;
-
- protected TerminalSupport(final boolean supported) {
- this.supported = supported;
- }
-
- public void init() throws Exception {
- if (shutdownTask != null) {
- ShutdownHooks.remove(shutdownTask);
- }
- // Register a task to restore the terminal on shutdown
- this.shutdownTask = ShutdownHooks.add(new Task()
- {
- public void run() throws Exception {
- restore();
- }
- });
- }
-
- public void restore() throws Exception {
- TerminalFactory.resetIf(this);
- if (shutdownTask != null) {
- ShutdownHooks.remove(shutdownTask);
- shutdownTask = null;
- }
- }
-
- public void reset() throws Exception {
- restore();
- init();
- }
-
- public final boolean isSupported() {
- return supported;
- }
-
- public synchronized boolean isAnsiSupported() {
- return ansiSupported;
- }
-
- protected synchronized void setAnsiSupported(final boolean supported) {
- this.ansiSupported = supported;
- Log.debug("Ansi supported: ", supported);
- }
-
- /**
- * Subclass to change behavior if needed.
- * @return the passed out
- */
- public OutputStream wrapOutIfNeeded(OutputStream out) {
- return out;
- }
-
- /**
- * Defaults to true which was the behaviour before this method was added.
- */
- public boolean hasWeirdWrap() {
- return true;
- }
-
- public int getWidth() {
- return DEFAULT_WIDTH;
- }
-
- public int getHeight() {
- return DEFAULT_HEIGHT;
- }
-
- public synchronized boolean isEchoEnabled() {
- return echoEnabled;
- }
-
- public synchronized void setEchoEnabled(final boolean enabled) {
- this.echoEnabled = enabled;
- Log.debug("Echo enabled: ", enabled);
- }
-
- public void disableInterruptCharacter() {
- }
-
- public void enableInterruptCharacter() {
- }
-
- public InputStream wrapInIfNeeded(InputStream in) throws IOException {
- return in;
- }
-
- public String getOutputEncoding() {
- // null for unknown
- return null;
- }
-}
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.internal.le/share/classes/jdk/internal/jline/UnixTerminal.java
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/UnixTerminal.java Tue Dec 11 11:45:43 2018 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,244 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import jdk.internal.jline.internal.Configuration;
-import jdk.internal.jline.internal.InfoCmp;
-import jdk.internal.jline.internal.Log;
-import jdk.internal.jline.internal.TerminalLineSettings;
-
-import static jdk.internal.jline.internal.Preconditions.checkNotNull;
-
-/**
- * Terminal that is used for unix platforms. Terminal initialization
- * is handled by issuing the stty command against the
- * /dev/tty file to disable character echoing and enable
- * character input. All known unix systems (including
- * Linux and Macintosh OS X) support the stty), so this
- * implementation should work for an reasonable POSIX system.
- *
- * @author Marc Prud'hommeaux
- * @author Dale Kemp
- * @author Jason Dillon
- * @author Jean-Baptiste Onofr\u00E9
- * @since 2.0
- */
-public class UnixTerminal
- extends TerminalSupport
- implements Terminal2
-{
- private final TerminalLineSettings settings;
- private final String type;
- private String intr;
- private String lnext;
- private Set bools = new HashSet();
- private Map ints = new HashMap();
- private Map strings = new HashMap();
-
- public UnixTerminal() throws Exception {
- this(TerminalLineSettings.DEFAULT_TTY, null);
- }
-
- public UnixTerminal(String ttyDevice) throws Exception {
- this(ttyDevice, null);
- }
-
- public UnixTerminal(String ttyDevice, String type) throws Exception {
- super(true);
- checkNotNull(ttyDevice);
- this.settings = TerminalLineSettings.getSettings(ttyDevice);
- if (type == null) {
- type = System.getenv("TERM");
- }
- this.type = type;
- parseInfoCmp();
- }
-
- public TerminalLineSettings getSettings() {
- return settings;
- }
-
- /**
- * Remove line-buffered input by invoking "stty -icanon min 1"
- * against the current terminal.
- */
- @Override
- public void init() throws Exception {
- super.init();
-
- setAnsiSupported(true);
-
- // Set the console to be character-buffered instead of line-buffered.
- // Make sure we're distinguishing carriage return from newline.
- // Allow ctrl-s keypress to be used (as forward search)
- //
- // Please note that FreeBSD does not seem to support -icrnl and thus
- // has to be handled separately. Otherwise the console will be "stuck"
- // and will neither accept input nor print anything to stdout.
- if (Configuration.getOsName().contains(TerminalFactory.FREEBSD)) {
- settings.set("-icanon min 1 -inlcr -ixon");
- } else {
- settings.set("-icanon min 1 -icrnl -inlcr -ixon");
- }
- settings.undef("dsusp");
-
- setEchoEnabled(false);
-
- parseInfoCmp();
- }
-
- /**
- * Restore the original terminal configuration, which can be used when
- * shutting down the console reader. The ConsoleReader cannot be
- * used after calling this method.
- */
- @Override
- public void restore() throws Exception {
- settings.restore();
- super.restore();
- }
-
- /**
- * Returns the value of stty columns param.
- */
- @Override
- public int getWidth() {
- int w = settings.getProperty("columns");
- return w < 1 ? DEFAULT_WIDTH : w;
- }
-
- /**
- * Returns the value of stty rows>/tt> param.
- */
- @Override
- public int getHeight() {
- int h = settings.getProperty("rows");
- return h < 1 ? DEFAULT_HEIGHT : h;
- }
-
- @Override
- public boolean hasWeirdWrap() {
- return getBooleanCapability("auto_right_margin")
- && getBooleanCapability("eat_newline_glitch");
- }
-
- @Override
- public synchronized void setEchoEnabled(final boolean enabled) {
- try {
- if (enabled) {
- settings.set("echo");
- }
- else {
- settings.set("-echo");
- }
- super.setEchoEnabled(enabled);
- }
- catch (Exception e) {
- if (e instanceof InterruptedException) {
- Thread.currentThread().interrupt();
- }
- Log.error("Failed to ", enabled ? "enable" : "disable", " echo", e);
- }
- }
-
- public void disableInterruptCharacter()
- {
- try {
- intr = getSettings().getPropertyAsString("intr");
- if ("".equals(intr)) {
- intr = null;
- }
- settings.undef("intr");
- }
- catch (Exception e) {
- if (e instanceof InterruptedException) {
- Thread.currentThread().interrupt();
- }
- Log.error("Failed to disable interrupt character", e);
- }
- }
-
- public void enableInterruptCharacter()
- {
- try {
- if (intr != null) {
- settings.set("intr", intr);
- }
- }
- catch (Exception e) {
- if (e instanceof InterruptedException) {
- Thread.currentThread().interrupt();
- }
- Log.error("Failed to enable interrupt character", e);
- }
- }
-
- public void disableLitteralNextCharacter()
- {
- try {
- lnext = getSettings().getPropertyAsString("lnext");
- if ("".equals(lnext)) {
- lnext = null;
- }
- settings.undef("lnext");
- }
- catch (Exception e) {
- if (e instanceof InterruptedException) {
- Thread.currentThread().interrupt();
- }
- Log.error("Failed to disable litteral next character", e);
- }
- }
-
- public void enableLitteralNextCharacter()
- {
- try {
- if (lnext != null) {
- settings.set("lnext", lnext);
- }
- }
- catch (Exception e) {
- if (e instanceof InterruptedException) {
- Thread.currentThread().interrupt();
- }
- Log.error("Failed to enable litteral next character", e);
- }
- }
-
- public boolean getBooleanCapability(String capability) {
- return bools.contains(capability);
- }
-
- public Integer getNumericCapability(String capability) {
- return ints.get(capability);
- }
-
- public String getStringCapability(String capability) {
- return strings.get(capability);
- }
-
- private void parseInfoCmp() {
- String capabilities = null;
- if (type != null) {
- try {
- capabilities = InfoCmp.getInfoCmp(type);
- } catch (Exception e) {
- }
- }
- if (capabilities == null) {
- capabilities = InfoCmp.getAnsiCaps();
- }
- InfoCmp.parseInfoCmp(capabilities, bools, ints, strings);
- }
-}
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.internal.le/share/classes/jdk/internal/jline/UnsupportedTerminal.java
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/UnsupportedTerminal.java Tue Dec 11 11:45:43 2018 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline;
-
-/**
- * An unsupported terminal.
- *
- * @author Marc Prud'hommeaux
- * @author Jason Dillon
- * @since 2.0
- */
-public class UnsupportedTerminal
- extends TerminalSupport
-{
- public UnsupportedTerminal() {
- this(false, true);
- }
-
- public UnsupportedTerminal(boolean ansiSupported, boolean echoEnabled) {
- super(false);
- setAnsiSupported(ansiSupported);
- setEchoEnabled(echoEnabled);
- }
-}
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.internal.le/share/classes/jdk/internal/jline/WindowsTerminal.java
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/WindowsTerminal.java Tue Dec 11 11:45:43 2018 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,617 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline;
-
-import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import jdk.internal.jline.extra.AnsiInterpretingOutputStream;
-import jdk.internal.jline.extra.AnsiInterpretingOutputStream.BufferState;
-import jdk.internal.jline.extra.AnsiInterpretingOutputStream.Performer;
-import jdk.internal.jline.internal.Configuration;
-import jdk.internal.jline.internal.Log;
-//import org.fusesource.jansi.internal.WindowsSupport;
-//import org.fusesource.jansi.internal.Kernel32;
-//import static org.fusesource.jansi.internal.Kernel32.*;
-
-import static jdk.internal.jline.WindowsTerminal.ConsoleMode.ENABLE_ECHO_INPUT;
-import static jdk.internal.jline.WindowsTerminal.ConsoleMode.ENABLE_LINE_INPUT;
-import static jdk.internal.jline.WindowsTerminal.ConsoleMode.ENABLE_PROCESSED_INPUT;
-import static jdk.internal.jline.WindowsTerminal.ConsoleMode.ENABLE_WINDOW_INPUT;
-
-/**
- * Terminal implementation for Microsoft Windows. Terminal initialization in
- * {@link #init} is accomplished by extracting the
- * jline_version.dll, saving it to the system temporary
- * directoy (determined by the setting of the java.io.tmpdir System
- * property), loading the library, and then calling the Win32 APIs SetConsoleMode and
- * GetConsoleMode to
- * disable character echoing.
- *
- *
- * By default, the {@link #wrapInIfNeeded(java.io.InputStream)} method will attempt
- * to test to see if the specified {@link InputStream} is {@link System#in} or a wrapper
- * around {@link FileDescriptor#in}, and if so, will bypass the character reading to
- * directly invoke the readc() method in the JNI library. This is so the class
- * can read special keys (like arrow keys) which are otherwise inaccessible via
- * the {@link System#in} stream. Using JNI reading can be bypassed by setting
- * the jline.WindowsTerminal.directConsole
system property
- * to false
.
- *
- *
- * @author Marc Prud'hommeaux
- * @author Jason Dillon
- * @since 2.0
- */
-public class WindowsTerminal
- extends TerminalSupport
-{
- public static final String DIRECT_CONSOLE = WindowsTerminal.class.getName() + ".directConsole";
-
- public static final String ANSI = WindowsTerminal.class.getName() + ".ansi";
-
- private boolean directConsole;
-
- private int originalMode;
-
- public WindowsTerminal() throws Exception {
- super(true);
- }
-
- @Override
- public void init() throws Exception {
- super.init();
-
-// setAnsiSupported(Configuration.getBoolean(ANSI, true));
- setAnsiSupported(true);
-
- //
- // FIXME: Need a way to disable direct console and sysin detection muck
- //
-
- setDirectConsole(Configuration.getBoolean(DIRECT_CONSOLE, true));
-
- this.originalMode = getConsoleMode();
- setConsoleMode(originalMode & ~ENABLE_ECHO_INPUT.code);
- setEchoEnabled(false);
- }
-
- /**
- * Restore the original terminal configuration, which can be used when
- * shutting down the console reader. The ConsoleReader cannot be
- * used after calling this method.
- */
- @Override
- public void restore() throws Exception {
- // restore the old console mode
- setConsoleMode(originalMode);
- super.restore();
- }
-
- @Override
- public int getWidth() {
- int w = getWindowsTerminalWidth();
- return w < 1 ? DEFAULT_WIDTH : w;
- }
-
- @Override
- public int getHeight() {
- int h = getWindowsTerminalHeight();
- return h < 1 ? DEFAULT_HEIGHT : h;
- }
-
- @Override
- public void setEchoEnabled(final boolean enabled) {
- // Must set these four modes at the same time to make it work fine.
- if (enabled) {
- setConsoleMode(getConsoleMode() |
- ENABLE_ECHO_INPUT.code |
- ENABLE_LINE_INPUT.code |
- ENABLE_WINDOW_INPUT.code);
- }
- else {
- setConsoleMode(getConsoleMode() &
- ~(ENABLE_LINE_INPUT.code |
- ENABLE_ECHO_INPUT.code |
- ENABLE_WINDOW_INPUT.code));
- }
- super.setEchoEnabled(enabled);
- }
-
- public void disableInterruptCharacter() {
- setConsoleMode(getConsoleMode() &
- ~(ENABLE_PROCESSED_INPUT.code));
- }
-
- public void enableInterruptCharacter() {
- setConsoleMode(getConsoleMode() |
- ENABLE_PROCESSED_INPUT.code);
- }
-
- /**
- * Whether or not to allow the use of the JNI console interaction.
- */
- public void setDirectConsole(final boolean flag) {
- this.directConsole = flag;
- Log.debug("Direct console: ", flag);
- }
-
- /**
- * Whether or not to allow the use of the JNI console interaction.
- */
- public Boolean getDirectConsole() {
- return directConsole;
- }
-
-
- @Override
- public InputStream wrapInIfNeeded(InputStream in) throws IOException {
- if (directConsole && isSystemIn(in)) {
- return new InputStream() {
- private byte[] buf = null;
- int bufIdx = 0;
-
- @Override
- public int read() throws IOException {
- while (buf == null || bufIdx == buf.length) {
- buf = readConsoleInput();
- bufIdx = 0;
- }
- int c = buf[bufIdx] & 0xFF;
- bufIdx++;
- return c;
- }
- };
- } else {
- return super.wrapInIfNeeded(in);
- }
- }
-
- protected boolean isSystemIn(final InputStream in) throws IOException {
- if (in == null) {
- return false;
- }
- else if (in == System.in) {
- return true;
- }
- else if (in instanceof FileInputStream && ((FileInputStream) in).getFD() == FileDescriptor.in) {
- return true;
- }
-
- return false;
- }
-
- @Override
- public OutputStream wrapOutIfNeeded(OutputStream out) {
- return new AnsiInterpretingOutputStream(getOutputEncoding(), out, new Performer() {
- @Override
- public BufferState getBufferState() throws IOException {
- out.flush();
- return WindowsTerminal.this.getBufferState();
- }
- @Override
- public void setCursorPosition(int cursorX, int cursorY) throws IOException {
- out.flush();
- WindowsTerminal.this.setCursorPosition(cursorX, cursorY);
- }
- });
- }
-
- @Override
- public String getOutputEncoding() {
- int codepage = getConsoleOutputCodepage();
- //http://docs.oracle.com/javase/6/docs/technotes/guides/intl/encoding.doc.html
- String charsetMS = "ms" + codepage;
- if (java.nio.charset.Charset.isSupported(charsetMS)) {
- return charsetMS;
- }
- String charsetCP = "cp" + codepage;
- if (java.nio.charset.Charset.isSupported(charsetCP)) {
- return charsetCP;
- }
- Log.debug("can't figure out the Java Charset of this code page (" + codepage + ")...");
- return super.getOutputEncoding();
- }
-
- //
- // Original code:
- //
-// private int getConsoleMode() {
-// return WindowsSupport.getConsoleMode();
-// }
-//
-// private void setConsoleMode(int mode) {
-// WindowsSupport.setConsoleMode(mode);
-// }
-//
-// private byte[] readConsoleInput() {
-// // XXX does how many events to read in one call matter?
-// INPUT_RECORD[] events = null;
-// try {
-// events = WindowsSupport.readConsoleInput(1);
-// } catch (IOException e) {
-// Log.debug("read Windows console input error: ", e);
-// }
-// if (events == null) {
-// return new byte[0];
-// }
-// StringBuilder sb = new StringBuilder();
-// for (int i = 0; i < events.length; i++ ) {
-// KEY_EVENT_RECORD keyEvent = events[i].keyEvent;
-// //Log.trace(keyEvent.keyDown? "KEY_DOWN" : "KEY_UP", "key code:", keyEvent.keyCode, "char:", (long)keyEvent.uchar);
-// if (keyEvent.keyDown) {
-// if (keyEvent.uchar > 0) {
-// // support some C1 control sequences: ALT + [@-_] (and [a-z]?) => ESC
-// // http://en.wikipedia.org/wiki/C0_and_C1_control_codes#C1_set
-// final int altState = KEY_EVENT_RECORD.LEFT_ALT_PRESSED | KEY_EVENT_RECORD.RIGHT_ALT_PRESSED;
-// // Pressing "Alt Gr" is translated to Alt-Ctrl, hence it has to be checked that Ctrl is _not_ pressed,
-// // otherwise inserting of "Alt Gr" codes on non-US keyboards would yield errors
-// final int ctrlState = KEY_EVENT_RECORD.LEFT_CTRL_PRESSED | KEY_EVENT_RECORD.RIGHT_CTRL_PRESSED;
-// if (((keyEvent.uchar >= '@' && keyEvent.uchar <= '_') || (keyEvent.uchar >= 'a' && keyEvent.uchar <= 'z'))
-// && ((keyEvent.controlKeyState & altState) != 0) && ((keyEvent.controlKeyState & ctrlState) == 0)) {
-// sb.append('\u001B'); // ESC
-// }
-//
-// sb.append(keyEvent.uchar);
-// continue;
-// }
-// // virtual keycodes: http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
-// // just add support for basic editing keys (no control state, no numpad keys)
-// String escapeSequence = null;
-// switch (keyEvent.keyCode) {
-// case 0x21: // VK_PRIOR PageUp
-// escapeSequence = "\u001B[5~";
-// break;
-// case 0x22: // VK_NEXT PageDown
-// escapeSequence = "\u001B[6~";
-// break;
-// case 0x23: // VK_END
-// escapeSequence = "\u001B[4~";
-// break;
-// case 0x24: // VK_HOME
-// escapeSequence = "\u001B[1~";
-// break;
-// case 0x25: // VK_LEFT
-// escapeSequence = "\u001B[D";
-// break;
-// case 0x26: // VK_UP
-// escapeSequence = "\u001B[A";
-// break;
-// case 0x27: // VK_RIGHT
-// escapeSequence = "\u001B[C";
-// break;
-// case 0x28: // VK_DOWN
-// escapeSequence = "\u001B[B";
-// break;
-// case 0x2D: // VK_INSERT
-// escapeSequence = "\u001B[2~";
-// break;
-// case 0x2E: // VK_DELETE
-// escapeSequence = "\u001B[3~";
-// break;
-// default:
-// break;
-// }
-// if (escapeSequence != null) {
-// for (int k = 0; k < keyEvent.repeatCount; k++) {
-// sb.append(escapeSequence);
-// }
-// }
-// } else {
-// // key up event
-// // support ALT+NumPad input method
-// if (keyEvent.keyCode == 0x12/*VK_MENU ALT key*/ && keyEvent.uchar > 0) {
-// sb.append(keyEvent.uchar);
-// }
-// }
-// }
-// return sb.toString().getBytes();
-// }
-//
-// private int getConsoleOutputCodepage() {
-// return Kernel32.GetConsoleOutputCP();
-// }
-//
-// private int getWindowsTerminalWidth() {
-// return WindowsSupport.getWindowsTerminalWidth();
-// }
-//
-// private int getWindowsTerminalHeight() {
-// return WindowsSupport.getWindowsTerminalHeight();
-// }
-
- //
- // Native Bits
- //
- static {
- System.loadLibrary("le");
- initIDs();
- }
-
- private static native void initIDs();
-
- protected native int getConsoleMode();
-
- protected native void setConsoleMode(int mode);
-
- private byte[] readConsoleInput() {
- KEY_EVENT_RECORD keyEvent = readKeyEvent();
-
- return convertKeys(keyEvent).getBytes();
- }
-
- public static String convertKeys(KEY_EVENT_RECORD keyEvent) {
- if (keyEvent == null) {
- return "";
- }
-
- StringBuilder sb = new StringBuilder();
-
- if (keyEvent.keyDown) {
- if (keyEvent.uchar > 0) {
- // support some C1 control sequences: ALT + [@-_] (and [a-z]?) => ESC
- // http://en.wikipedia.org/wiki/C0_and_C1_control_codes#C1_set
- final int altState = KEY_EVENT_RECORD.ALT_PRESSED;
- // Pressing "Alt Gr" is translated to Alt-Ctrl, hence it has to be checked that Ctrl is _not_ pressed,
- // otherwise inserting of "Alt Gr" codes on non-US keyboards would yield errors
- final int ctrlState = KEY_EVENT_RECORD.CTRL_PRESSED;
-
- boolean handled = false;
-
- if ((keyEvent.controlKeyState & ctrlState) != 0) {
- switch (keyEvent.keyCode) {
- case 0x43: //Ctrl-C
- sb.append("\003");
- handled = true;
- break;
- }
- }
-
- if ((keyEvent.controlKeyState & KEY_EVENT_RECORD.SHIFT_PRESSED) != 0) {
- switch (keyEvent.keyCode) {
- case 0x09: //Shift-Tab
- sb.append("\033\133\132");
- handled = true;
- break;
- }
- }
-
- if (!handled) {
- if (((keyEvent.uchar >= '@' && keyEvent.uchar <= '_') || (keyEvent.uchar >= 'a' && keyEvent.uchar <= 'z'))
- && ((keyEvent.controlKeyState & altState) != 0) && ((keyEvent.controlKeyState & ctrlState) == 0)) {
- sb.append('\u001B'); // ESC
- }
-
- sb.append(keyEvent.uchar);
- }
- } else {
- // virtual keycodes: http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
- // xterm escape codes: E. Moy, S. Gildea and T. Dickey, "XTerm Control Sequences":
- // http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
- // http://xorg.freedesktop.org/releases/X11R6.8.1/PDF/ctlseqs.pdf
- // just add support for basic editing keys and function keys
- String escapeSequence = null;
- switch (keyEvent.keyCode) {
- case 0x21: // VK_PRIOR PageUp
- escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[5~", "\u001B[5;%d~");
- break;
- case 0x22: // VK_NEXT PageDown
- escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[6~", "\u001B[6;%d~");
- break;
- case 0x23: // VK_END
- escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[4~", "\u001B[4;%d~");
- break;
- case 0x24: // VK_HOME
- escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[1~", "\u001B[1;%d~");
- break;
- case 0x25: // VK_LEFT
- escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[D", "\u001B[1;%dD");
- break;
- case 0x26: // VK_UP
- escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[A", "\u001B[1;%dA");
- break;
- case 0x27: // VK_RIGHT
- escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[C", "\u001B[1;%dC");
- break;
- case 0x28: // VK_DOWN
- escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[B", "\u001B[1;%dB");
- break;
- case 0x2D: // VK_INSERT
- escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[2~", "\u001B[2;%d~");
- break;
- case 0x2E: // VK_DELETE
- escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[3~", "\u001B[3;%d~");
- break;
- case 0x70: // VK_F1
- escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001BOP", "\u001BO%dP");
- break;
- case 0x71: // VK_F2
- escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001BOQ", "\u001BO%dQ");
- break;
- case 0x72: // VK_F3
- escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001BOR", "\u001BO%dR");
- break;
- case 0x73: // VK_F4
- escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001BOS", "\u001BO%dS");
- break;
- case 0x74: // VK_F5
- escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[15~", "\u001B[15;%d~");
- break;
- case 0x75: // VK_F6
- escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[17~", "\u001B[17;%d~");
- break;
- case 0x76: // VK_F7
- escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[18~", "\u001B[18;%d~");
- break;
- case 0x77: // VK_F8
- escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[19~", "\u001B[19;%d~");
- break;
- case 0x78: // VK_F9
- escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[20~", "\u001B[20;%d~");
- break;
- case 0x79: // VK_F10
- escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[21~", "\u001B[21;%d~");
- break;
- case 0x7A: // VK_F11
- escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[23~", "\u001B[23;%d~");
- break;
- case 0x7B: // VK_F12
- escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[24~", "\u001B[24;%d~");
- break;
- default:
- break;
- }
- if (escapeSequence != null) {
- for (int k = 0; k < keyEvent.repeatCount; k++) {
- sb.append(escapeSequence);
- }
- }
- }
- } else {
- // key up event
- // support ALT+NumPad input method
- if (keyEvent.keyCode == 0x12/*VK_MENU ALT key*/ && keyEvent.uchar > 0) {
- sb.append(keyEvent.uchar);
- }
- }
- return sb.toString();
- }
-
- private static String escapeSequence(int controlKeyState, String noControlSequence, String withControlSequence) {
- int controlNum = 1;
-
- if ((controlKeyState & KEY_EVENT_RECORD.SHIFT_PRESSED) != 0) {
- controlNum += 1;
- }
-
- if ((controlKeyState & KEY_EVENT_RECORD.ALT_PRESSED) != 0) {
- controlNum += 2;
- }
-
- if ((controlKeyState & KEY_EVENT_RECORD.CTRL_PRESSED) != 0) {
- controlNum += 4;
- }
-
- if (controlNum > 1) {
- return String.format(withControlSequence, controlNum);
- } else {
- return noControlSequence;
- }
- }
-
- private native KEY_EVENT_RECORD readKeyEvent();
-
- public static class KEY_EVENT_RECORD {
- public final static int ALT_PRESSED = 0x3;
- public final static int CTRL_PRESSED = 0xC;
- public final static int SHIFT_PRESSED = 0x10;
- public final boolean keyDown;
- public final char uchar;
- public final int controlKeyState;
- public final int keyCode;
- public final int repeatCount;
-
- public KEY_EVENT_RECORD(boolean keyDown, char uchar, int controlKeyState, int keyCode, int repeatCount) {
- this.keyDown = keyDown;
- this.uchar = uchar;
- this.controlKeyState = controlKeyState;
- this.keyCode = keyCode;
- this.repeatCount = repeatCount;
- }
-
- }
-
- private native int getConsoleOutputCodepage();
-
- private native int getWindowsTerminalWidth();
-
- private native int getWindowsTerminalHeight();
-
- private native BufferState getBufferState();
-
- private native void setCursorPosition(int x, int y);
-
- /**
- * Console mode
- *
- * Constants copied wincon.h.
- */
- public static enum ConsoleMode
- {
- /**
- * The ReadFile or ReadConsole function returns only when a carriage return
- * character is read. If this mode is disable, the functions return when one
- * or more characters are available.
- */
- ENABLE_LINE_INPUT(2),
-
- /**
- * Characters read by the ReadFile or ReadConsole function are written to
- * the active screen buffer as they are read. This mode can be used only if
- * the ENABLE_LINE_INPUT mode is also enabled.
- */
- ENABLE_ECHO_INPUT(4),
-
- /**
- * CTRL+C is processed by the system and is not placed in the input buffer.
- * If the input buffer is being read by ReadFile or ReadConsole, other
- * control keys are processed by the system and are not returned in the
- * ReadFile or ReadConsole buffer. If the ENABLE_LINE_INPUT mode is also
- * enabled, backspace, carriage return, and linefeed characters are handled
- * by the system.
- */
- ENABLE_PROCESSED_INPUT(1),
-
- /**
- * User interactions that change the size of the console screen buffer are
- * reported in the console's input buffee. Information about these events
- * can be read from the input buffer by applications using
- * theReadConsoleInput function, but not by those using ReadFile
- * orReadConsole.
- */
- ENABLE_WINDOW_INPUT(8),
-
- /**
- * If the mouse pointer is within the borders of the console window and the
- * window has the keyboard focus, mouse events generated by mouse movement
- * and button presses are placed in the input buffer. These events are
- * discarded by ReadFile or ReadConsole, even when this mode is enabled.
- */
- ENABLE_MOUSE_INPUT(16),
-
- /**
- * When enabled, text entered in a console window will be inserted at the
- * current cursor location and all text following that location will not be
- * overwritten. When disabled, all following text will be overwritten. An OR
- * operation must be performed with this flag and the ENABLE_EXTENDED_FLAGS
- * flag to enable this functionality.
- */
- ENABLE_PROCESSED_OUTPUT(1),
-
- /**
- * This flag enables the user to use the mouse to select and edit text. To
- * enable this option, use the OR to combine this flag with
- * ENABLE_EXTENDED_FLAGS.
- */
- ENABLE_WRAP_AT_EOL_OUTPUT(2),;
-
- public final int code;
-
- ConsoleMode(final int code) {
- this.code = code;
- }
- }
-
-}
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.internal.le/share/classes/jdk/internal/jline/console/ConsoleKeys.java
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/ConsoleKeys.java Tue Dec 11 11:45:43 2018 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,387 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import jdk.internal.jline.internal.Log;
-
-/**
- * @author St\u00E5le W. Pedersen
- */
-public class ConsoleKeys {
-
- private KeyMap keys;
-
- private Map keyMaps;
- private Map variables = new HashMap();
-
- public ConsoleKeys(String appName, URL inputrcUrl) {
- keyMaps = KeyMap.keyMaps();
- setVar("editing-mode", "emacs");
- loadKeys(appName, inputrcUrl);
- String editingMode = variables.get("editing-mode");
- if ("vi".equalsIgnoreCase(editingMode)) {
- keys = keyMaps.get(KeyMap.VI_INSERT);
- } else if ("emacs".equalsIgnoreCase(editingMode)) {
- keys = keyMaps.get(KeyMap.EMACS);
- }
- }
-
- protected boolean setKeyMap (String name) {
- KeyMap map = keyMaps.get(name);
- if (map == null) {
- return false;
- }
- this.keys = map;
- return true;
- }
-
- protected Map getKeyMaps() {
- return keyMaps;
- }
-
- protected KeyMap getKeys() {
- return keys;
- }
-
- protected void setKeys(KeyMap keys) {
- this.keys = keys;
- }
-
- protected void loadKeys(String appName, URL inputrcUrl) {
- keys = keyMaps.get(KeyMap.EMACS);
-
- try {
- InputStream input = inputrcUrl.openStream();
- try {
- loadKeys(input, appName);
- Log.debug("Loaded user configuration: ", inputrcUrl);
- }
- finally {
- try {
- input.close();
- } catch (IOException e) {
- // Ignore
- }
- }
- }
- catch (IOException e) {
- if (inputrcUrl.getProtocol().equals("file")) {
- File file = new File(inputrcUrl.getPath());
- if (file.exists()) {
- Log.warn("Unable to read user configuration: ", inputrcUrl, e);
- }
- } else {
- Log.warn("Unable to read user configuration: ", inputrcUrl, e);
- }
- }
- }
-
- private void loadKeys(InputStream input, String appName) throws IOException {
- BufferedReader reader = new BufferedReader( new java.io.InputStreamReader( input ) );
- String line;
- boolean parsing = true;
- List ifsStack = new ArrayList();
- while ( (line = reader.readLine()) != null ) {
- try {
- line = line.trim();
- if (line.length() == 0) {
- continue;
- }
- if (line.charAt(0) == '#') {
- continue;
- }
- int i = 0;
- if (line.charAt(i) == '$') {
- String cmd;
- String args;
- for (++i; i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t'); i++);
- int s = i;
- for (; i < line.length() && (line.charAt(i) != ' ' && line.charAt(i) != '\t'); i++);
- cmd = line.substring(s, i);
- for (; i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t'); i++);
- s = i;
- for (; i < line.length() && (line.charAt(i) != ' ' && line.charAt(i) != '\t'); i++);
- args = line.substring(s, i);
- if ("if".equalsIgnoreCase(cmd)) {
- ifsStack.add( parsing );
- if (!parsing) {
- continue;
- }
- if (args.startsWith("term=")) {
- // TODO
- } else if (args.startsWith("mode=")) {
- String mode = variables.get("editing-mode");
- parsing = args.substring("mode=".length()).equalsIgnoreCase(mode);
- } else {
- parsing = args.equalsIgnoreCase(appName);
- }
- } else if ("else".equalsIgnoreCase(cmd)) {
- if (ifsStack.isEmpty()) {
- throw new IllegalArgumentException("$else found without matching $if");
- }
- boolean invert = true;
- for (boolean b : ifsStack) {
- if (!b) {
- invert = false;
- break;
- }
- }
- if (invert) {
- parsing = !parsing;
- }
- } else if ("endif".equalsIgnoreCase(cmd)) {
- if (ifsStack.isEmpty()) {
- throw new IllegalArgumentException("endif found without matching $if");
- }
- parsing = ifsStack.remove( ifsStack.size() - 1 );
- } else if ("include".equalsIgnoreCase(cmd)) {
- // TODO
- }
- continue;
- }
- if (!parsing) {
- continue;
- }
- boolean equivalency;
- String keySeq = "";
- if (line.charAt(i++) == '"') {
- boolean esc = false;
- for (;; i++) {
- if (i >= line.length()) {
- throw new IllegalArgumentException("Missing closing quote on line '" + line + "'");
- }
- if (esc) {
- esc = false;
- } else if (line.charAt(i) == '\\') {
- esc = true;
- } else if (line.charAt(i) == '"') {
- break;
- }
- }
- }
- for (; i < line.length() && line.charAt(i) != ':'
- && line.charAt(i) != ' ' && line.charAt(i) != '\t'
- ; i++);
- keySeq = line.substring(0, i);
- equivalency = i + 1 < line.length() && line.charAt(i) == ':' && line.charAt(i + 1) == '=';
- i++;
- if (equivalency) {
- i++;
- }
- if (keySeq.equalsIgnoreCase("set")) {
- String key;
- String val;
- for (; i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t'); i++);
- int s = i;
- for (; i < line.length() && (line.charAt(i) != ' ' && line.charAt(i) != '\t'); i++);
- key = line.substring( s, i );
- for (; i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t'); i++);
- s = i;
- for (; i < line.length() && (line.charAt(i) != ' ' && line.charAt(i) != '\t'); i++);
- val = line.substring( s, i );
- setVar( key, val );
- } else {
- for (; i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t'); i++);
- int start = i;
- if (i < line.length() && (line.charAt(i) == '\'' || line.charAt(i) == '\"')) {
- char delim = line.charAt(i++);
- boolean esc = false;
- for (;; i++) {
- if (i >= line.length()) {
- break;
- }
- if (esc) {
- esc = false;
- } else if (line.charAt(i) == '\\') {
- esc = true;
- } else if (line.charAt(i) == delim) {
- break;
- }
- }
- }
- for (; i < line.length() && line.charAt(i) != ' ' && line.charAt(i) != '\t'; i++);
- String val = line.substring(Math.min(start, line.length()), Math.min(i, line.length()));
- if (keySeq.charAt(0) == '"') {
- keySeq = translateQuoted(keySeq);
- } else {
- // Bind key name
- String keyName = keySeq.lastIndexOf('-') > 0 ? keySeq.substring( keySeq.lastIndexOf('-') + 1 ) : keySeq;
- char key = getKeyFromName(keyName);
- keyName = keySeq.toLowerCase();
- keySeq = "";
- if (keyName.contains("meta-") || keyName.contains("m-")) {
- keySeq += "\u001b";
- }
- if (keyName.contains("control-") || keyName.contains("c-") || keyName.contains("ctrl-")) {
- key = (char)(Character.toUpperCase( key ) & 0x1f);
- }
- keySeq += key;
- }
- if (val.length() > 0 && (val.charAt(0) == '\'' || val.charAt(0) == '\"')) {
- keys.bind( keySeq, translateQuoted(val) );
- } else {
- String operationName = val.replace('-', '_').toUpperCase();
- try {
- keys.bind(keySeq, Operation.valueOf(operationName));
- } catch(IllegalArgumentException e) {
- Log.info("Unable to bind key for unsupported operation: ", val);
- }
- }
- }
- } catch (IllegalArgumentException e) {
- Log.warn("Unable to parse user configuration: ", e);
- }
- }
- }
-
- private static String translateQuoted(String keySeq) {
- int i;
- String str = keySeq.substring( 1, keySeq.length() - 1 );
- keySeq = "";
- for (i = 0; i < str.length(); i++) {
- char c = str.charAt(i);
- if (c == '\\') {
- boolean ctrl = str.regionMatches(i, "\\C-", 0, 3)|| str.regionMatches(i, "\\M-\\C-", 0, 6);
- boolean meta = str.regionMatches(i, "\\M-", 0, 3)|| str.regionMatches(i, "\\C-\\M-", 0, 6);
- i += (meta ? 3 : 0) + (ctrl ? 3 : 0) + (!meta && !ctrl ? 1 : 0);
- if (i >= str.length()) {
- break;
- }
- c = str.charAt(i);
- if (meta) {
- keySeq += "\u001b";
- }
- if (ctrl) {
- c = c == '?' ? 0x7f : (char)(Character.toUpperCase( c ) & 0x1f);
- }
- if (!meta && !ctrl) {
- switch (c) {
- case 'a': c = 0x07; break;
- case 'b': c = '\b'; break;
- case 'd': c = 0x7f; break;
- case 'e': c = 0x1b; break;
- case 'f': c = '\f'; break;
- case 'n': c = '\n'; break;
- case 'r': c = '\r'; break;
- case 't': c = '\t'; break;
- case 'v': c = 0x0b; break;
- case '\\': c = '\\'; break;
- case '0': case '1': case '2': case '3':
- case '4': case '5': case '6': case '7':
- c = 0;
- for (int j = 0; j < 3; j++, i++) {
- if (i >= str.length()) {
- break;
- }
- int k = Character.digit(str.charAt(i), 8);
- if (k < 0) {
- break;
- }
- c = (char)(c * 8 + k);
- }
- c &= 0xFF;
- break;
- case 'x':
- i++;
- c = 0;
- for (int j = 0; j < 2; j++, i++) {
- if (i >= str.length()) {
- break;
- }
- int k = Character.digit(str.charAt(i), 16);
- if (k < 0) {
- break;
- }
- c = (char)(c * 16 + k);
- }
- c &= 0xFF;
- break;
- case 'u':
- i++;
- c = 0;
- for (int j = 0; j < 4; j++, i++) {
- if (i >= str.length()) {
- break;
- }
- int k = Character.digit(str.charAt(i), 16);
- if (k < 0) {
- break;
- }
- c = (char)(c * 16 + k);
- }
- break;
- }
- }
- keySeq += c;
- } else {
- keySeq += c;
- }
- }
- return keySeq;
- }
-
- private static char getKeyFromName(String name) {
- if ("DEL".equalsIgnoreCase(name) || "Rubout".equalsIgnoreCase(name)) {
- return 0x7f;
- } else if ("ESC".equalsIgnoreCase(name) || "Escape".equalsIgnoreCase(name)) {
- return '\033';
- } else if ("LFD".equalsIgnoreCase(name) || "NewLine".equalsIgnoreCase(name)) {
- return '\n';
- } else if ("RET".equalsIgnoreCase(name) || "Return".equalsIgnoreCase(name)) {
- return '\r';
- } else if ("SPC".equalsIgnoreCase(name) || "Space".equalsIgnoreCase(name)) {
- return ' ';
- } else if ("Tab".equalsIgnoreCase(name)) {
- return '\t';
- } else {
- return name.charAt(0);
- }
- }
-
- private void setVar(String key, String val) {
- if ("keymap".equalsIgnoreCase(key)) {
- if (keyMaps.containsKey(val)) {
- keys = keyMaps.get(val);
- }
- } else if ("blink-matching-paren".equals(key)) {
- if ("on".equalsIgnoreCase(val)) {
- keys.setBlinkMatchingParen(true);
- } else if ("off".equalsIgnoreCase(val)) {
- keys.setBlinkMatchingParen(false);
- }
- }
-
- /*
- * Technically variables should be defined as a functor class
- * so that validation on the variable value can be done at parse
- * time. This is a stop-gap.
- */
- variables.put(key, val);
- }
-
- /**
- * Retrieves the value of a variable that was set in the .inputrc file
- * during processing
- * @param var The variable name
- * @return The variable value.
- */
- public String getVariable(String var) {
- return variables.get (var);
- }
-}
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.internal.le/share/classes/jdk/internal/jline/console/ConsoleReader.java
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/ConsoleReader.java Tue Dec 11 11:45:43 2018 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,4086 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console;
-
-//import java.awt.*;
-//import java.awt.datatransfer.Clipboard;
-//import java.awt.datatransfer.DataFlavor;
-//import java.awt.datatransfer.Transferable;
-//import java.awt.datatransfer.UnsupportedFlavorException;
-//import java.awt.event.ActionListener;
-import java.io.BufferedReader;
-import java.io.Closeable;
-import java.io.File;
-import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Reader;
-import java.io.Writer;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.lang.System;
-import java.lang.reflect.InvocationTargetException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.ResourceBundle;
-import java.util.Stack;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import jdk.internal.jline.DefaultTerminal2;
-import jdk.internal.jline.Terminal;
-import jdk.internal.jline.Terminal2;
-import jdk.internal.jline.TerminalFactory;
-import jdk.internal.jline.UnixTerminal;
-import jdk.internal.jline.console.completer.CandidateListCompletionHandler;
-import jdk.internal.jline.console.completer.Completer;
-import jdk.internal.jline.console.completer.CompletionHandler;
-import jdk.internal.jline.console.history.History;
-import jdk.internal.jline.console.history.MemoryHistory;
-import jdk.internal.jline.internal.Ansi;
-import jdk.internal.jline.internal.Configuration;
-import jdk.internal.jline.internal.Curses;
-import jdk.internal.jline.internal.InputStreamReader;
-import jdk.internal.jline.internal.Log;
-import jdk.internal.jline.internal.NonBlockingInputStream;
-import jdk.internal.jline.internal.Nullable;
-import jdk.internal.jline.internal.TerminalLineSettings;
-import jdk.internal.jline.internal.Urls;
-
-import static jdk.internal.jline.internal.Preconditions.checkNotNull;
-
-/**
- * A reader for console applications. It supports custom tab-completion,
- * saveable command history, and command line editing. On some platforms,
- * platform-specific commands will need to be issued before the reader will
- * function properly. See {@link jline.Terminal#init} for convenience
- * methods for issuing platform-specific setup commands.
- *
- * @author Marc Prud'hommeaux
- * @author Jason Dillon
- * @author Guillaume Nodet
- */
-public class ConsoleReader implements Closeable
-{
- public static final String JLINE_NOBELL = "jline.nobell";
-
- public static final String JLINE_ESC_TIMEOUT = "jline.esc.timeout";
-
- public static final String JLINE_INPUTRC = "jline.inputrc";
-
- public static final String INPUT_RC = ".inputrc";
-
- public static final String DEFAULT_INPUT_RC = "/etc/inputrc";
-
- public static final String JLINE_EXPAND_EVENTS = "jline.expandevents";
-
- public static final char BACKSPACE = '\b';
-
- public static final char RESET_LINE = '\r';
-
- public static final char KEYBOARD_BELL = '\07';
-
- public static final char NULL_MASK = 0;
-
- public static final int TAB_WIDTH = 8;
-
- private static final ResourceBundle
- resources = ResourceBundle.getBundle(CandidateListCompletionHandler.class.getName());
-
- private static final int ESCAPE = 27;
- private static final int READ_EXPIRED = -2;
-
- private final Terminal2 terminal;
-
- private final Writer out;
-
- private final CursorBuffer buf = new CursorBuffer();
- private boolean cursorOk;
-
- private String prompt;
- private int promptLen;
-
- private boolean expandEvents = Configuration.getBoolean(JLINE_EXPAND_EVENTS, true);
-
- private boolean bellEnabled = !Configuration.getBoolean(JLINE_NOBELL, true);
-
- private boolean handleUserInterrupt = false;
-
- private boolean handleLitteralNext = true;
-
- private Character mask;
-
- private Character echoCharacter;
-
- private CursorBuffer originalBuffer = null;
-
- private StringBuffer searchTerm = null;
-
- private String previousSearchTerm = "";
-
- private int searchIndex = -1;
-
- private int parenBlinkTimeout = 500;
-
- // Reading buffers
- private final StringBuilder opBuffer = new StringBuilder();
- private final Stack pushBackChar = new Stack();
-
- /*
- * The reader and the nonBlockingInput go hand-in-hand. The reader wraps
- * the nonBlockingInput, but we have to retain a handle to it so that
- * we can shut down its blocking read thread when we go away.
- */
- private NonBlockingInputStream in;
- private long escapeTimeout;
- private Reader reader;
-
- /**
- * Last character searched for with a vi character search
- */
- private char charSearchChar = 0; // Character to search for
- private char charSearchLastInvokeChar = 0; // Most recent invocation key
- private char charSearchFirstInvokeChar = 0;// First character that invoked
-
- /**
- * The vi yank buffer
- */
- private String yankBuffer = "";
-
- private KillRing killRing = new KillRing();
-
- private String encoding;
-
- private boolean quotedInsert;
-
- private boolean recording;
-
- private String macro = "";
-
- private String appName;
-
- private URL inputrcUrl;
-
- private ConsoleKeys consoleKeys;
-
- private String commentBegin = null;
-
- private boolean skipLF = false;
-
- /**
- * Set to true if the reader should attempt to detect copy-n-paste. The
- * effect of this that an attempt is made to detect if tab is quickly
- * followed by another character, then it is assumed that the tab was
- * a literal tab as part of a copy-and-paste operation and is inserted as
- * such.
- */
- private boolean copyPasteDetection = false;
-
- /*
- * Current internal state of the line reader
- */
- private State state = State.NORMAL;
-
- /**
- * Possible states in which the current readline operation may be in.
- */
- private static enum State {
- /**
- * The user is just typing away
- */
- NORMAL,
- /**
- * In the middle of a emacs seach
- */
- SEARCH,
- FORWARD_SEARCH,
- /**
- * VI "yank-to" operation ("y" during move mode)
- */
- VI_YANK_TO,
- /**
- * VI "delete-to" operation ("d" during move mode)
- */
- VI_DELETE_TO,
- /**
- * VI "change-to" operation ("c" during move mode)
- */
- VI_CHANGE_TO
- }
-
- public ConsoleReader() throws IOException {
- this(null, new FileInputStream(FileDescriptor.in), System.out, null);
- }
-
- public ConsoleReader(final InputStream in, final OutputStream out) throws IOException {
- this(null, in, out, null);
- }
-
- public ConsoleReader(final InputStream in, final OutputStream out, final Terminal term) throws IOException {
- this(null, in, out, term);
- }
-
- public ConsoleReader(final @Nullable String appName, final InputStream in, final OutputStream out, final @Nullable Terminal term) throws IOException {
- this(appName, in, out, term, null);
- }
-
- public ConsoleReader(final @Nullable String appName, final InputStream in, final OutputStream out, final @Nullable Terminal term, final @Nullable String encoding)
- throws IOException
- {
- this.appName = appName != null ? appName : "JLine";
- this.encoding = encoding != null ? encoding : Configuration.getEncoding();
- Terminal terminal = term != null ? term : TerminalFactory.get();
- this.terminal = terminal instanceof Terminal2 ? (Terminal2) terminal : new DefaultTerminal2(terminal);
- String outEncoding = terminal.getOutputEncoding() != null? terminal.getOutputEncoding() : this.encoding;
- this.out = new OutputStreamWriter(terminal.wrapOutIfNeeded(out), outEncoding);
- setInput( in );
-
- this.inputrcUrl = getInputRc();
-
- consoleKeys = new ConsoleKeys(this.appName, inputrcUrl);
-
- if (terminal instanceof UnixTerminal
- && TerminalLineSettings.DEFAULT_TTY.equals(((UnixTerminal) terminal).getSettings().getTtyDevice())
- && Configuration.getBoolean("jline.sigcont", false)) {
- setupSigCont();
- }
- }
-
- private void setupSigCont() {
- // Check that sun.misc.SignalHandler and sun.misc.Signal exists
- try {
- Class> signalClass = Class.forName("sun.misc.Signal");
- Class> signalHandlerClass = Class.forName("sun.misc.SignalHandler");
- // Implement signal handler
- Object signalHandler = Proxy.newProxyInstance(getClass().getClassLoader(),
- new Class>[]{signalHandlerClass}, new InvocationHandler() {
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- // only method we are proxying is handle()
- terminal.init();
- try {
- drawLine();
- flush();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return null;
- }
- });
- // Register the signal handler, this code is equivalent to:
- // Signal.handle(new Signal("CONT"), signalHandler);
- signalClass.getMethod("handle", signalClass, signalHandlerClass).invoke(null, signalClass.getConstructor(String.class).newInstance("CONT"), signalHandler);
- } catch (ClassNotFoundException cnfe) {
- // sun.misc Signal handler classes don't exist
- } catch (Exception e) {
- // Ignore this one too, if the above failed, the signal API is incompatible with what we're expecting
- }
- }
-
- /**
- * Retrieve the URL for the inputrc configuration file in effect. Intended
- * use is for instantiating ConsoleKeys, to read inputrc variables.
- */
- public static URL getInputRc() throws IOException {
- String path = Configuration.getString(JLINE_INPUTRC);
- if (path == null) {
- File f = new File(Configuration.getUserHome(), INPUT_RC);
- if (!f.exists()) {
- f = new File(DEFAULT_INPUT_RC);
- }
- return f.toURI().toURL();
- } else {
- return Urls.create(path);
- }
- }
-
- public KeyMap getKeys() {
- return consoleKeys.getKeys();
- }
-
- void setInput(final InputStream in) throws IOException {
- this.escapeTimeout = Configuration.getLong(JLINE_ESC_TIMEOUT, 100);
- boolean nonBlockingEnabled =
- escapeTimeout > 0L
- && terminal.isSupported()
- && in != null;
-
- /*
- * If we had a non-blocking thread already going, then shut it down
- * and start a new one.
- */
- if (this.in != null) {
- this.in.shutdown();
- }
-
- final InputStream wrapped = terminal.wrapInIfNeeded( in );
-
- this.in = new NonBlockingInputStream(wrapped, nonBlockingEnabled);
- this.reader = new InputStreamReader( this.in, encoding );
- }
-
- /**
- * Shuts the console reader down. This method should be called when you
- * have completed using the reader as it shuts down and cleans up resources
- * that would otherwise be "leaked".
- */
- @Override
- public void close() {
- if (in != null) {
- in.shutdown();
- }
- }
-
- /**
- * Shuts the console reader down. The same as {@link #close()}.
- * @deprecated Use {@link #close()} instead.
- */
- @Deprecated
- public void shutdown() {
- this.close();
- }
-
- /**
- * Shuts down the ConsoleReader if the JVM attempts to clean it up.
- */
- @Override
- @SuppressWarnings("deprecation")
- protected void finalize() throws Throwable {
- try {
- close();
- }
- finally {
- super.finalize();
- }
- }
-
- public InputStream getInput() {
- return in;
- }
-
- public Writer getOutput() {
- return out;
- }
-
- public Terminal getTerminal() {
- return terminal;
- }
-
- public CursorBuffer getCursorBuffer() {
- return buf;
- }
-
- public void setExpandEvents(final boolean expand) {
- this.expandEvents = expand;
- }
-
- public boolean getExpandEvents() {
- return expandEvents;
- }
-
- /**
- * Enables or disables copy and paste detection. The effect of enabling this
- * this setting is that when a tab is received immediately followed by another
- * character, the tab will not be treated as a completion, but as a tab literal.
- * @param onoff true if detection is enabled
- */
- public void setCopyPasteDetection(final boolean onoff) {
- copyPasteDetection = onoff;
- }
-
- /**
- * @return true if copy and paste detection is enabled.
- */
- public boolean isCopyPasteDetectionEnabled() {
- return copyPasteDetection;
- }
-
- /**
- * Set whether the console bell is enabled.
- *
- * @param enabled true if enabled; false otherwise
- * @since 2.7
- */
- public void setBellEnabled(boolean enabled) {
- this.bellEnabled = enabled;
- }
-
- /**
- * Get whether the console bell is enabled
- *
- * @return true if enabled; false otherwise
- * @since 2.7
- */
- public boolean getBellEnabled() {
- return bellEnabled;
- }
-
- /**
- * Set whether user interrupts (ctrl-C) are handled by having JLine
- * throw {@link UserInterruptException} from {@link #readLine}.
- * Otherwise, the JVM will handle {@code SIGINT} as normal, which
- * usually causes it to exit. The default is {@code false}.
- *
- * @since 2.10
- */
- public void setHandleUserInterrupt(boolean enabled)
- {
- this.handleUserInterrupt = enabled;
- }
-
- /**
- * Get whether user interrupt handling is enabled
- *
- * @return true if enabled; false otherwise
- * @since 2.10
- */
- public boolean getHandleUserInterrupt()
- {
- return handleUserInterrupt;
- }
-
- /**
- * Set wether literal next are handled by JLine.
- *
- * @since 2.13
- */
- public void setHandleLitteralNext(boolean handleLitteralNext) {
- this.handleLitteralNext = handleLitteralNext;
- }
-
- /**
- * Get wether literal next are handled by JLine.
- *
- * @since 2.13
- */
- public boolean getHandleLitteralNext() {
- return handleLitteralNext;
- }
-
- /**
- * Sets the string that will be used to start a comment when the
- * insert-comment key is struck.
- * @param commentBegin The begin comment string.
- * @since 2.7
- */
- public void setCommentBegin(String commentBegin) {
- this.commentBegin = commentBegin;
- }
-
- /**
- * @return the string that will be used to start a comment when the
- * insert-comment key is struck.
- * @since 2.7
- */
- public String getCommentBegin() {
- String str = commentBegin;
-
- if (str == null) {
- str = consoleKeys.getVariable("comment-begin");
- if (str == null) {
- str = "#";
- }
- }
- return str;
- }
-
- public void setPrompt(final String prompt) {
- this.prompt = prompt;
- this.promptLen = (prompt == null) ? 0 : wcwidth(Ansi.stripAnsi(lastLine(prompt)), 0);
- }
-
- public String getPrompt() {
- return prompt;
- }
-
- /**
- * Set the echo character. For example, to have "*" entered when a password is typed:
- *
- * myConsoleReader.setEchoCharacter(new Character('*'));
- *
- * Setting the character to null
will restore normal character echoing.
- * Setting the character to Character.valueOf(0)
will cause nothing to be echoed.
- *
- * @param c the character to echo to the console in place of the typed character.
- */
- public void setEchoCharacter(final Character c) {
- this.echoCharacter = c;
- }
-
- /**
- * Returns the echo character.
- */
- public Character getEchoCharacter() {
- return echoCharacter;
- }
-
- /**
- * Erase the current line.
- *
- * @return false if we failed (e.g., the buffer was empty)
- */
- protected final boolean resetLine() throws IOException {
- if (buf.cursor == 0) {
- return false;
- }
-
- StringBuilder killed = new StringBuilder();
-
- while (buf.cursor > 0) {
- char c = buf.current();
- if (c == 0) {
- break;
- }
-
- killed.append(c);
- backspace();
- }
-
- String copy = killed.reverse().toString();
- killRing.addBackwards(copy);
-
- return true;
- }
-
- int wcwidth(CharSequence str, int pos) {
- return wcwidth(str, 0, str.length(), pos);
- }
-
- int wcwidth(CharSequence str, int start, int end, int pos) {
- int cur = pos;
- for (int i = start; i < end;) {
- int ucs;
- char c1 = str.charAt(i++);
- if (!Character.isHighSurrogate(c1) || i >= end) {
- ucs = c1;
- } else {
- char c2 = str.charAt(i);
- if (Character.isLowSurrogate(c2)) {
- i++;
- ucs = Character.toCodePoint(c1, c2);
- } else {
- ucs = c1;
- }
- }
- cur += wcwidth(ucs, cur);
- }
- return cur - pos;
- }
-
- int wcwidth(int ucs, int pos) {
- if (ucs == '\t') {
- return nextTabStop(pos);
- } else if (ucs < 32) {
- return 2;
- } else {
- int w = WCWidth.wcwidth(ucs);
- return w > 0 ? w : 0;
- }
- }
-
- int nextTabStop(int pos) {
- int tabWidth = TAB_WIDTH;
- int width = getTerminal().getWidth();
- int mod = (pos + tabWidth - 1) % tabWidth;
- int npos = pos + tabWidth - mod;
- return npos < width ? npos - pos : width - pos;
- }
-
- int getCursorPosition() {
- return promptLen + wcwidth(buf.buffer, 0, buf.cursor, promptLen);
- }
-
- /**
- * Returns the text after the last '\n'.
- * prompt is returned if no '\n' characters are present.
- * null is returned if prompt is null.
- */
- private static String lastLine(String str) {
- if (str == null) return "";
- int last = str.lastIndexOf("\n");
-
- if (last >= 0) {
- return str.substring(last + 1, str.length());
- }
-
- return str;
- }
-
- /**
- * Move the cursor position to the specified absolute index.
- */
- public boolean setCursorPosition(final int position) throws IOException {
- if (position == buf.cursor) {
- return true;
- }
-
- return moveCursor(position - buf.cursor) != 0;
- }
-
- /**
- * Set the current buffer's content to the specified {@link String}. The
- * visual console will be modified to show the current buffer.
- *
- * @param buffer the new contents of the buffer.
- */
- private void setBuffer(final String buffer) throws IOException {
- // don't bother modifying it if it is unchanged
- if (buffer.equals(buf.buffer.toString())) {
- return;
- }
-
- // obtain the difference between the current buffer and the new one
- int sameIndex = 0;
-
- for (int i = 0, l1 = buffer.length(), l2 = buf.buffer.length(); (i < l1)
- && (i < l2); i++) {
- if (buffer.charAt(i) == buf.buffer.charAt(i)) {
- sameIndex++;
- }
- else {
- break;
- }
- }
-
- int diff = buf.cursor - sameIndex;
- if (diff < 0) { // we can't backspace here so try from the end of the buffer
- moveToEnd();
- diff = buf.buffer.length() - sameIndex;
- }
-
- backspace(diff); // go back for the differences
- killLine(); // clear to the end of the line
- buf.buffer.setLength(sameIndex); // the new length
- putString(buffer.substring(sameIndex)); // append the differences
- }
-
- private void setBuffer(final CharSequence buffer) throws IOException {
- setBuffer(String.valueOf(buffer));
- }
-
- private void setBufferKeepPos(final String buffer) throws IOException {
- int pos = buf.cursor;
- setBuffer(buffer);
- setCursorPosition(pos);
- }
-
- private void setBufferKeepPos(final CharSequence buffer) throws IOException {
- setBufferKeepPos(String.valueOf(buffer));
- }
-
- /**
- * Output put the prompt + the current buffer
- */
- public void drawLine() throws IOException {
- String prompt = getPrompt();
- if (prompt != null) {
- rawPrint(prompt);
- }
-
- fmtPrint(buf.buffer, 0, buf.cursor, promptLen);
-
- // force drawBuffer to check for weird wrap (after clear screen)
- drawBuffer();
- }
-
- /**
- * Clear the line and redraw it.
- */
- public void redrawLine() throws IOException {
- tputs("carriage_return");
- drawLine();
- }
-
- /**
- * Clear the buffer and add its contents to the history.
- *
- * @return the former contents of the buffer.
- */
- final String finishBuffer() throws IOException { // FIXME: Package protected because used by tests
- String str = buf.buffer.toString();
- String historyLine = str;
-
- if (expandEvents) {
- try {
- str = expandEvents(str);
- // all post-expansion occurrences of '!' must have been escaped, so re-add escape to each
- historyLine = str.replace("!", "\\!");
- // only leading '^' results in expansion, so only re-add escape for that case
- historyLine = historyLine.replaceAll("^\\^", "\\\\^");
- } catch(IllegalArgumentException e) {
- Log.error("Could not expand event", e);
- beep();
- buf.clear();
- str = "";
- }
- }
-
- // we only add it to the history if the buffer is not empty
- // and if mask is null, since having a mask typically means
- // the string was a password. We clear the mask after this call
- if (str.length() > 0) {
- if (mask == null && isHistoryEnabled()) {
- history.add(historyLine);
- }
- else {
- mask = null;
- }
- }
-
- history.moveToEnd();
-
- buf.buffer.setLength(0);
- buf.cursor = 0;
-
- return str;
- }
-
- /**
- * Expand event designator such as !!, !#, !3, etc...
- * See http://www.gnu.org/software/bash/manual/html_node/Event-Designators.html
- */
- @SuppressWarnings("fallthrough")
- protected String expandEvents(String str) throws IOException {
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < str.length(); i++) {
- char c = str.charAt(i);
- switch (c) {
- case '\\':
- // any '\!' should be considered an expansion escape, so skip expansion and strip the escape character
- // a leading '\^' should be considered an expansion escape, so skip expansion and strip the escape character
- // otherwise, add the escape
- if (i + 1 < str.length()) {
- char nextChar = str.charAt(i+1);
- if (nextChar == '!' || (nextChar == '^' && i == 0)) {
- c = nextChar;
- i++;
- }
- }
- sb.append(c);
- break;
- case '!':
- if (i + 1 < str.length()) {
- c = str.charAt(++i);
- boolean neg = false;
- String rep = null;
- int i1, idx;
- switch (c) {
- case '!':
- if (history.size() == 0) {
- throw new IllegalArgumentException("!!: event not found");
- }
- rep = history.get(history.index() - 1).toString();
- break;
- case '#':
- sb.append(sb.toString());
- break;
- case '?':
- i1 = str.indexOf('?', i + 1);
- if (i1 < 0) {
- i1 = str.length();
- }
- String sc = str.substring(i + 1, i1);
- i = i1;
- idx = searchBackwards(sc);
- if (idx < 0) {
- throw new IllegalArgumentException("!?" + sc + ": event not found");
- } else {
- rep = history.get(idx).toString();
- }
- break;
- case '$':
- if (history.size() == 0) {
- throw new IllegalArgumentException("!$: event not found");
- }
- String previous = history.get(history.index() - 1).toString().trim();
- int lastSpace = previous.lastIndexOf(' ');
- if(lastSpace != -1) {
- rep = previous.substring(lastSpace+1);
- } else {
- rep = previous;
- }
- break;
- case ' ':
- case '\t':
- sb.append('!');
- sb.append(c);
- break;
- case '-':
- neg = true;
- i++;
- // fall through
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- i1 = i;
- for (; i < str.length(); i++) {
- c = str.charAt(i);
- if (c < '0' || c > '9') {
- break;
- }
- }
- idx = 0;
- try {
- idx = Integer.parseInt(str.substring(i1, i));
- } catch (NumberFormatException e) {
- throw new IllegalArgumentException((neg ? "!-" : "!") + str.substring(i1, i) + ": event not found");
- }
- if (neg) {
- if (idx > 0 && idx <= history.size()) {
- rep = (history.get(history.index() - idx)).toString();
- } else {
- throw new IllegalArgumentException((neg ? "!-" : "!") + str.substring(i1, i) + ": event not found");
- }
- } else {
- if (idx > history.index() - history.size() && idx <= history.index()) {
- rep = (history.get(idx - 1)).toString();
- } else {
- throw new IllegalArgumentException((neg ? "!-" : "!") + str.substring(i1, i) + ": event not found");
- }
- }
- break;
- default:
- String ss = str.substring(i);
- i = str.length();
- idx = searchBackwards(ss, history.index(), true);
- if (idx < 0) {
- throw new IllegalArgumentException("!" + ss + ": event not found");
- } else {
- rep = history.get(idx).toString();
- }
- break;
- }
- if (rep != null) {
- sb.append(rep);
- }
- } else {
- sb.append(c);
- }
- break;
- case '^':
- if (i == 0) {
- int i1 = str.indexOf('^', i + 1);
- int i2 = str.indexOf('^', i1 + 1);
- if (i2 < 0) {
- i2 = str.length();
- }
- if (i1 > 0 && i2 > 0) {
- String s1 = str.substring(i + 1, i1);
- String s2 = str.substring(i1 + 1, i2);
- String s = history.get(history.index() - 1).toString().replace(s1, s2);
- sb.append(s);
- i = i2 + 1;
- break;
- }
- }
- sb.append(c);
- break;
- default:
- sb.append(c);
- break;
- }
- }
- String result = sb.toString();
- if (!str.equals(result)) {
- fmtPrint(result, getCursorPosition());
- println();
- flush();
- }
- return result;
-
- }
-
- /**
- * Write out the specified string to the buffer and the output stream.
- */
- public void putString(final CharSequence str) throws IOException {
- int pos = getCursorPosition();
- buf.write(str);
- if (mask == null) {
- // no masking
- fmtPrint(str, pos);
- } else if (mask == NULL_MASK) {
- // don't print anything
- } else {
- rawPrint(mask, str.length());
- }
- drawBuffer();
- }
-
- /**
- * Redraw the rest of the buffer from the cursor onwards. This is necessary
- * for inserting text into the buffer.
- *
- * @param clear the number of characters to clear after the end of the buffer
- */
- private void drawBuffer(final int clear) throws IOException {
- // debug ("drawBuffer: " + clear);
- int nbChars = buf.length() - buf.cursor;
- if (buf.cursor != buf.length() || clear != 0) {
- if (mask != null) {
- if (mask != NULL_MASK) {
- rawPrint(mask, nbChars);
- } else {
- nbChars = 0;
- }
- } else {
- fmtPrint(buf.buffer, buf.cursor, buf.length());
- }
- }
- int cursorPos = promptLen + wcwidth(buf.buffer, 0, buf.length(), promptLen);
- if (terminal.hasWeirdWrap() && !cursorOk) {
- int width = terminal.getWidth();
- // best guess on whether the cursor is in that weird location...
- // Need to do this without calling ansi cursor location methods
- // otherwise it breaks paste of wrapped lines in xterm.
- if (cursorPos > 0 && (cursorPos % width == 0)) {
- // the following workaround is reverse-engineered from looking
- // at what bash sent to the terminal in the same situation
- rawPrint(' '); // move cursor to next line by printing dummy space
- tputs("carriage_return"); // CR / not newline.
- }
- cursorOk = true;
- }
- clearAhead(clear, cursorPos);
- back(nbChars);
- }
-
- /**
- * Redraw the rest of the buffer from the cursor onwards. This is necessary
- * for inserting text into the buffer.
- */
- private void drawBuffer() throws IOException {
- drawBuffer(0);
- }
-
- /**
- * Clear ahead the specified number of characters without moving the cursor.
- *
- * @param num the number of characters to clear
- * @param pos the current screen cursor position
- */
- private void clearAhead(int num, final int pos) throws IOException {
- if (num == 0) return;
-
- int width = terminal.getWidth();
- // Use kill line
- if (terminal.getStringCapability("clr_eol") != null) {
- int cur = pos;
- int c0 = cur % width;
- // Erase end of current line
- int nb = Math.min(num, width - c0);
- tputs("clr_eol");
- num -= nb;
- // Loop
- while (num > 0) {
- // Move to beginning of next line
- int prev = cur;
- cur = cur - cur % width + width;
- moveCursorFromTo(prev, cur);
- // Erase
- nb = Math.min(num, width);
- tputs("clr_eol");
- num -= nb;
- }
- moveCursorFromTo(cur, pos);
- }
- // Terminal does not wrap on the right margin
- else if (!terminal.getBooleanCapability("auto_right_margin")) {
- int cur = pos;
- int c0 = cur % width;
- // Erase end of current line
- int nb = Math.min(num, width - c0);
- rawPrint(' ', nb);
- num -= nb;
- cur += nb;
- // Loop
- while (num > 0) {
- // Move to beginning of next line
- moveCursorFromTo(cur, ++cur);
- // Erase
- nb = Math.min(num, width);
- rawPrint(' ', nb);
- num -= nb;
- cur += nb;
- }
- moveCursorFromTo(cur, pos);
- }
- // Simple erasure
- else {
- rawPrint(' ', num);
- moveCursorFromTo(pos + num, pos);
- }
- }
-
- /**
- * Move the visual cursor backward without modifying the buffer cursor.
- */
- protected void back(final int num) throws IOException {
- if (num == 0) return;
- int i0 = promptLen + wcwidth(buf.buffer, 0, buf.cursor, promptLen);
- int i1 = i0 + ((mask != null) ? num : wcwidth(buf.buffer, buf.cursor, buf.cursor + num, i0));
- moveCursorFromTo(i1, i0);
- }
-
- /**
- * Flush the console output stream. This is important for printout out single characters (like a backspace or
- * keyboard) that we want the console to handle immediately.
- */
- public void flush() throws IOException {
- out.flush();
- }
-
- private int backspaceAll() throws IOException {
- return backspace(Integer.MAX_VALUE);
- }
-
- /**
- * Issue num backspaces.
- *
- * @return the number of characters backed up
- */
- private int backspace(final int num) throws IOException {
- if (buf.cursor == 0) {
- return 0;
- }
-
- int count = - moveCursor(-num);
- int clear = wcwidth(buf.buffer, buf.cursor, buf.cursor + count, getCursorPosition());
- buf.buffer.delete(buf.cursor, buf.cursor + count);
-
- drawBuffer(clear);
- return count;
- }
-
- /**
- * Issue a backspace.
- *
- * @return true if successful
- */
- public boolean backspace() throws IOException {
- return backspace(1) == 1;
- }
-
- protected boolean moveToEnd() throws IOException {
- if (buf.cursor == buf.length()) {
- return true;
- }
- return moveCursor(buf.length() - buf.cursor) > 0;
- }
-
- /**
- * Delete the character at the current position and redraw the remainder of the buffer.
- */
- private boolean deleteCurrentCharacter() throws IOException {
- if (buf.length() == 0 || buf.cursor == buf.length()) {
- return false;
- }
-
- buf.buffer.deleteCharAt(buf.cursor);
- drawBuffer(1);
- return true;
- }
-
- /**
- * This method is calling while doing a delete-to ("d"), change-to ("c"),
- * or yank-to ("y") and it filters out only those movement operations
- * that are allowable during those operations. Any operation that isn't
- * allow drops you back into movement mode.
- *
- * @param op The incoming operation to remap
- * @return The remaped operation
- */
- private Operation viDeleteChangeYankToRemap (Operation op) {
- switch (op) {
- case VI_EOF_MAYBE:
- case ABORT:
- case BACKWARD_CHAR:
- case FORWARD_CHAR:
- case END_OF_LINE:
- case VI_MATCH:
- case VI_BEGINNING_OF_LINE_OR_ARG_DIGIT:
- case VI_ARG_DIGIT:
- case VI_PREV_WORD:
- case VI_END_WORD:
- case VI_CHAR_SEARCH:
- case VI_NEXT_WORD:
- case VI_FIRST_PRINT:
- case VI_GOTO_MARK:
- case VI_COLUMN:
- case VI_DELETE_TO:
- case VI_YANK_TO:
- case VI_CHANGE_TO:
- return op;
-
- default:
- return Operation.VI_MOVEMENT_MODE;
- }
- }
-
- /**
- * Deletes the previous character from the cursor position
- * @param count number of times to do it.
- * @return true if it was done.
- */
- private boolean viRubout(int count) throws IOException {
- boolean ok = true;
- for (int i = 0; ok && i < count; i++) {
- ok = backspace();
- }
- return ok;
- }
-
- /**
- * Deletes the character you are sitting on and sucks the rest of
- * the line in from the right.
- * @param count Number of times to perform the operation.
- * @return true if its works, false if it didn't
- */
- private boolean viDelete(int count) throws IOException {
- boolean ok = true;
- for (int i = 0; ok && i < count; i++) {
- ok = deleteCurrentCharacter();
- }
- return ok;
- }
-
- /**
- * Switches the case of the current character from upper to lower
- * or lower to upper as necessary and advances the cursor one
- * position to the right.
- * @param count The number of times to repeat
- * @return true if it completed successfully, false if not all
- * case changes could be completed.
- */
- private boolean viChangeCase(int count) throws IOException {
- boolean ok = true;
- for (int i = 0; ok && i < count; i++) {
-
- ok = buf.cursor < buf.buffer.length ();
- if (ok) {
- char ch = buf.buffer.charAt(buf.cursor);
- if (Character.isUpperCase(ch)) {
- ch = Character.toLowerCase(ch);
- }
- else if (Character.isLowerCase(ch)) {
- ch = Character.toUpperCase(ch);
- }
- buf.buffer.setCharAt(buf.cursor, ch);
- drawBuffer(1);
- moveCursor(1);
- }
- }
- return ok;
- }
-
- /**
- * Implements the vi change character command (in move-mode "r"
- * followed by the character to change to).
- * @param count Number of times to perform the action
- * @param c The character to change to
- * @return Whether or not there were problems encountered
- */
- private boolean viChangeChar(int count, int c) throws IOException {
- // EOF, ESC, or CTRL-C aborts.
- if (c < 0 || c == '\033' || c == '\003') {
- return true;
- }
-
- boolean ok = true;
- for (int i = 0; ok && i < count; i++) {
- ok = buf.cursor < buf.buffer.length ();
- if (ok) {
- buf.buffer.setCharAt(buf.cursor, (char) c);
- drawBuffer(1);
- if (i < (count-1)) {
- moveCursor(1);
- }
- }
- }
- return ok;
- }
-
- /**
- * This is a close facsimile of the actual vi previous word logic. In
- * actual vi words are determined by boundaries of identity characterse.
- * This logic is a bit more simple and simply looks at white space or
- * digits or characters. It should be revised at some point.
- *
- * @param count number of iterations
- * @return true if the move was successful, false otherwise
- */
- private boolean viPreviousWord(int count) throws IOException {
- boolean ok = true;
- if (buf.cursor == 0) {
- return false;
- }
-
- int pos = buf.cursor - 1;
- for (int i = 0; pos > 0 && i < count; i++) {
- // If we are on white space, then move back.
- while (pos > 0 && isWhitespace(buf.buffer.charAt(pos))) {
- --pos;
- }
-
- while (pos > 0 && !isDelimiter(buf.buffer.charAt(pos-1))) {
- --pos;
- }
-
- if (pos > 0 && i < (count-1)) {
- --pos;
- }
- }
- setCursorPosition(pos);
- return ok;
- }
-
- /**
- * Performs the vi "delete-to" action, deleting characters between a given
- * span of the input line.
- * @param startPos The start position
- * @param endPos The end position.
- * @param isChange If true, then the delete is part of a change operationg
- * (e.g. "c$" is change-to-end-of line, so we first must delete to end
- * of line to start the change
- * @return true if it succeeded, false otherwise
- */
- private boolean viDeleteTo(int startPos, int endPos, boolean isChange) throws IOException {
- if (startPos == endPos) {
- return true;
- }
-
- if (endPos < startPos) {
- int tmp = endPos;
- endPos = startPos;
- startPos = tmp;
- }
-
- setCursorPosition(startPos);
- buf.cursor = startPos;
- buf.buffer.delete(startPos, endPos);
- drawBuffer(endPos - startPos);
-
- // If we are doing a delete operation (e.g. "d$") then don't leave the
- // cursor dangling off the end. In reality the "isChange" flag is silly
- // what is really happening is that if we are in "move-mode" then the
- // cursor can't be moved off the end of the line, but in "edit-mode" it
- // is ok, but I have no easy way of knowing which mode we are in.
- if (! isChange && startPos > 0 && startPos == buf.length()) {
- moveCursor(-1);
- }
- return true;
- }
-
- /**
- * Implement the "vi" yank-to operation. This operation allows you
- * to yank the contents of the current line based upon a move operation,
- * for exaple "yw" yanks the current word, "3yw" yanks 3 words, etc.
- *
- * @param startPos The starting position from which to yank
- * @param endPos The ending position to which to yank
- * @return true if the yank succeeded
- */
- private boolean viYankTo(int startPos, int endPos) throws IOException {
- int cursorPos = startPos;
-
- if (endPos < startPos) {
- int tmp = endPos;
- endPos = startPos;
- startPos = tmp;
- }
-
- if (startPos == endPos) {
- yankBuffer = "";
- return true;
- }
-
- yankBuffer = buf.buffer.substring(startPos, endPos);
-
- /*
- * It was a movement command that moved the cursor to find the
- * end position, so put the cursor back where it started.
- */
- setCursorPosition(cursorPos);
- return true;
- }
-
- /**
- * Pasts the yank buffer to the right of the current cursor position
- * and moves the cursor to the end of the pasted region.
- *
- * @param count Number of times to perform the operation.
- * @return true if it worked, false otherwise
- */
- private boolean viPut(int count) throws IOException {
- if (yankBuffer.length () == 0) {
- return true;
- }
- if (buf.cursor < buf.buffer.length ()) {
- moveCursor(1);
- }
- for (int i = 0; i < count; i++) {
- putString(yankBuffer);
- }
- moveCursor(-1);
- return true;
- }
-
- /**
- * Searches forward of the current position for a character and moves
- * the cursor onto it.
- * @param count Number of times to repeat the process.
- * @param ch The character to search for
- * @return true if the char was found, false otherwise
- */
- private boolean viCharSearch(int count, int invokeChar, int ch) throws IOException {
- if (ch < 0 || invokeChar < 0) {
- return false;
- }
-
- char searchChar = (char)ch;
- boolean isForward;
- boolean stopBefore;
-
- /*
- * The character stuff turns out to be hairy. Here is how it works:
- * f - search forward for ch
- * F - search backward for ch
- * t - search forward for ch, but stop just before the match
- * T - search backward for ch, but stop just after the match
- * ; - After [fFtT;], repeat the last search, after ',' reverse it
- * , - After [fFtT;], reverse the last search, after ',' repeat it
- */
- if (invokeChar == ';' || invokeChar == ',') {
- // No recent search done? Then bail
- if (charSearchChar == 0) {
- return false;
- }
-
- // Reverse direction if switching between ',' and ';'
- if (charSearchLastInvokeChar == ';' || charSearchLastInvokeChar == ',') {
- if (charSearchLastInvokeChar != invokeChar) {
- charSearchFirstInvokeChar = switchCase(charSearchFirstInvokeChar);
- }
- }
- else {
- if (invokeChar == ',') {
- charSearchFirstInvokeChar = switchCase(charSearchFirstInvokeChar);
- }
- }
-
- searchChar = charSearchChar;
- }
- else {
- charSearchChar = searchChar;
- charSearchFirstInvokeChar = (char) invokeChar;
- }
-
- charSearchLastInvokeChar = (char)invokeChar;
-
- isForward = Character.isLowerCase(charSearchFirstInvokeChar);
- stopBefore = (Character.toLowerCase(charSearchFirstInvokeChar) == 't');
-
- boolean ok = false;
-
- if (isForward) {
- while (count-- > 0) {
- int pos = buf.cursor + 1;
- while (pos < buf.buffer.length()) {
- if (buf.buffer.charAt(pos) == searchChar) {
- setCursorPosition(pos);
- ok = true;
- break;
- }
- ++pos;
- }
- }
-
- if (ok) {
- if (stopBefore)
- moveCursor(-1);
-
- /*
- * When in yank-to, move-to, del-to state we actually want to
- * go to the character after the one we landed on to make sure
- * that the character we ended up on is included in the
- * operation
- */
- if (isInViMoveOperationState()) {
- moveCursor(1);
- }
- }
- }
- else {
- while (count-- > 0) {
- int pos = buf.cursor - 1;
- while (pos >= 0) {
- if (buf.buffer.charAt(pos) == searchChar) {
- setCursorPosition(pos);
- ok = true;
- break;
- }
- --pos;
- }
- }
-
- if (ok && stopBefore)
- moveCursor(1);
- }
-
- return ok;
- }
-
- private static char switchCase(char ch) {
- if (Character.isUpperCase(ch)) {
- return Character.toLowerCase(ch);
- }
- return Character.toUpperCase(ch);
- }
-
- /**
- * @return true if line reader is in the middle of doing a change-to
- * delete-to or yank-to.
- */
- private final boolean isInViMoveOperationState() {
- return state == State.VI_CHANGE_TO
- || state == State.VI_DELETE_TO
- || state == State.VI_YANK_TO;
- }
-
- /**
- * This is a close facsimile of the actual vi next word logic.
- * As with viPreviousWord() this probably needs to be improved
- * at some point.
- *
- * @param count number of iterations
- * @return true if the move was successful, false otherwise
- */
- private boolean viNextWord(int count) throws IOException {
- int pos = buf.cursor;
- int end = buf.buffer.length();
-
- for (int i = 0; pos < end && i < count; i++) {
- // Skip over letter/digits
- while (pos < end && !isDelimiter(buf.buffer.charAt(pos))) {
- ++pos;
- }
-
- /*
- * Don't you love special cases? During delete-to and yank-to
- * operations the word movement is normal. However, during a
- * change-to, the trailing spaces behind the last word are
- * left in tact.
- */
- if (i < (count-1) || !(state == State.VI_CHANGE_TO)) {
- while (pos < end && isDelimiter(buf.buffer.charAt(pos))) {
- ++pos;
- }
- }
- }
-
- setCursorPosition(pos);
- return true;
- }
-
- /**
- * Implements a close facsimile of the vi end-of-word movement.
- * If the character is on white space, it takes you to the end
- * of the next word. If it is on the last character of a word
- * it takes you to the next of the next word. Any other character
- * of a word, takes you to the end of the current word.
- *
- * @param count Number of times to repeat the action
- * @return true if it worked.
- */
- private boolean viEndWord(int count) throws IOException {
- int pos = buf.cursor;
- int end = buf.buffer.length();
-
- for (int i = 0; pos < end && i < count; i++) {
- if (pos < (end-1)
- && !isDelimiter(buf.buffer.charAt(pos))
- && isDelimiter(buf.buffer.charAt (pos+1))) {
- ++pos;
- }
-
- // If we are on white space, then move back.
- while (pos < end && isDelimiter(buf.buffer.charAt(pos))) {
- ++pos;
- }
-
- while (pos < (end-1) && !isDelimiter(buf.buffer.charAt(pos+1))) {
- ++pos;
- }
- }
- setCursorPosition(pos);
- return true;
- }
-
- private boolean previousWord() throws IOException {
- while (isDelimiter(buf.current()) && (moveCursor(-1) != 0)) {
- // nothing
- }
-
- while (!isDelimiter(buf.current()) && (moveCursor(-1) != 0)) {
- // nothing
- }
-
- return true;
- }
-
- private boolean nextWord() throws IOException {
- while (isDelimiter(buf.nextChar()) && (moveCursor(1) != 0)) {
- // nothing
- }
-
- while (!isDelimiter(buf.nextChar()) && (moveCursor(1) != 0)) {
- // nothing
- }
-
- return true;
- }
-
- /**
- * Deletes to the beginning of the word that the cursor is sitting on.
- * If the cursor is on white-space, it deletes that and to the beginning
- * of the word before it. If the user is not on a word or whitespace
- * it deletes up to the end of the previous word.
- *
- * @param count Number of times to perform the operation
- * @return true if it worked, false if you tried to delete too many words
- */
- private boolean unixWordRubout(int count) throws IOException {
- boolean success = true;
- StringBuilder killed = new StringBuilder();
-
- for (; count > 0; --count) {
- if (buf.cursor == 0) {
- success = false;
- break;
- }
-
- while (isWhitespace(buf.current())) {
- char c = buf.current();
- if (c == 0) {
- break;
- }
-
- killed.append(c);
- backspace();
- }
-
- while (!isWhitespace(buf.current())) {
- char c = buf.current();
- if (c == 0) {
- break;
- }
-
- killed.append(c);
- backspace();
- }
- }
-
- String copy = killed.reverse().toString();
- killRing.addBackwards(copy);
-
- return success;
- }
-
- private String insertComment(boolean isViMode) throws IOException {
- String comment = this.getCommentBegin();
- setCursorPosition(0);
- putString(comment);
- if (isViMode) {
- consoleKeys.setKeyMap(KeyMap.VI_INSERT);
- }
- return accept();
- }
-
- /**
- * Implements vi search ("/" or "?").
- */
- @SuppressWarnings("fallthrough")
- private int viSearch(char searchChar) throws IOException {
- boolean isForward = (searchChar == '/');
-
- /*
- * This is a little gross, I'm sure there is a more appropriate way
- * of saving and restoring state.
- */
- CursorBuffer origBuffer = buf.copy();
-
- // Clear the contents of the current line and
- setCursorPosition (0);
- killLine();
-
- // Our new "prompt" is the character that got us into search mode.
- putString(Character.toString(searchChar));
- flush();
-
- boolean isAborted = false;
- boolean isComplete = false;
-
- /*
- * Readline doesn't seem to do any special character map handling
- * here, so I think we are safe.
- */
- int ch = -1;
- while (!isAborted && !isComplete && (ch = readCharacter()) != -1) {
- switch (ch) {
- case '\033': // ESC
- /*
- * The ESC behavior doesn't appear to be readline behavior,
- * but it is a little tweak of my own. I like it.
- */
- isAborted = true;
- break;
- case '\010': // Backspace
- case '\177': // Delete
- backspace();
- /*
- * Backspacing through the "prompt" aborts the search.
- */
- if (buf.cursor == 0) {
- isAborted = true;
- }
- break;
- case '\012': // NL
- case '\015': // CR
- isComplete = true;
- break;
- default:
- putString(Character.toString((char) ch));
- }
-
- flush();
- }
-
- // If we aborted, then put ourself at the end of the original buffer.
- if (ch == -1 || isAborted) {
- setCursorPosition(0);
- killLine();
- putString(origBuffer.buffer);
- setCursorPosition(origBuffer.cursor);
- return -1;
- }
-
- /*
- * The first character of the buffer was the search character itself
- * so we discard it.
- */
- String searchTerm = buf.buffer.substring(1);
- int idx = -1;
-
- /*
- * The semantics of the history thing is gross when you want to
- * explicitly iterate over entries (without an iterator) as size()
- * returns the actual number of entries in the list but get()
- * doesn't work the way you think.
- */
- int end = history.index();
- int start = (end <= history.size()) ? 0 : end - history.size();
-
- if (isForward) {
- for (int i = start; i < end; i++) {
- if (history.get(i).toString().contains(searchTerm)) {
- idx = i;
- break;
- }
- }
- }
- else {
- for (int i = end-1; i >= start; i--) {
- if (history.get(i).toString().contains(searchTerm)) {
- idx = i;
- break;
- }
- }
- }
-
- /*
- * No match? Then restore what we were working on, but make sure
- * the cursor is at the beginning of the line.
- */
- if (idx == -1) {
- setCursorPosition(0);
- killLine();
- putString(origBuffer.buffer);
- setCursorPosition(0);
- return -1;
- }
-
- /*
- * Show the match.
- */
- setCursorPosition(0);
- killLine();
- putString(history.get(idx));
- setCursorPosition(0);
- flush();
-
- /*
- * While searching really only the "n" and "N" keys are interpreted
- * as movement, any other key is treated as if you are editing the
- * line with it, so we return it back up to the caller for interpretation.
- */
- isComplete = false;
- while (!isComplete && (ch = readCharacter()) != -1) {
- boolean forward = isForward;
- switch (ch) {
- case 'p': case 'P':
- forward = !isForward;
- // Fallthru
- case 'n': case 'N':
- boolean isMatch = false;
- if (forward) {
- for (int i = idx+1; !isMatch && i < end; i++) {
- if (history.get(i).toString().contains(searchTerm)) {
- idx = i;
- isMatch = true;
- }
- }
- }
- else {
- for (int i = idx - 1; !isMatch && i >= start; i--) {
- if (history.get(i).toString().contains(searchTerm)) {
- idx = i;
- isMatch = true;
- }
- }
- }
- if (isMatch) {
- setCursorPosition(0);
- killLine();
- putString(history.get(idx));
- setCursorPosition(0);
- }
- break;
- default:
- isComplete = true;
- }
- flush();
- }
-
- /*
- * Complete?
- */
- return ch;
- }
-
- public void setParenBlinkTimeout(int timeout) {
- parenBlinkTimeout = timeout;
- }
-
- private void insertClose(String s) throws IOException {
- putString(s);
- int closePosition = buf.cursor;
-
- moveCursor(-1);
- viMatch();
-
-
- if (in.isNonBlockingEnabled()) {
- in.peek(parenBlinkTimeout);
- }
-
- setCursorPosition(closePosition);
- flush();
- }
-
- /**
- * Implements vi style bracket matching ("%" command). The matching
- * bracket for the current bracket type that you are sitting on is matched.
- * The logic works like so:
- * @return true if it worked, false if the cursor was not on a bracket
- * character or if there was no matching bracket.
- */
- private boolean viMatch() throws IOException {
- int pos = buf.cursor;
-
- if (pos == buf.length()) {
- return false;
- }
-
- int type = getBracketType(buf.buffer.charAt (pos));
- int move = (type < 0) ? -1 : 1;
- int count = 1;
-
- if (type == 0)
- return false;
-
- while (count > 0) {
- pos += move;
-
- // Fell off the start or end.
- if (pos < 0 || pos >= buf.buffer.length ()) {
- return false;
- }
-
- int curType = getBracketType(buf.buffer.charAt (pos));
- if (curType == type) {
- ++count;
- }
- else if (curType == -type) {
- --count;
- }
- }
-
- /*
- * Slight adjustment for delete-to, yank-to, change-to to ensure
- * that the matching paren is consumed
- */
- if (move > 0 && isInViMoveOperationState())
- ++pos;
-
- setCursorPosition(pos);
- flush();
- return true;
- }
-
- /**
- * Given a character determines what type of bracket it is (paren,
- * square, curly, or none).
- * @param ch The character to check
- * @return 1 is square, 2 curly, 3 parent, or zero for none. The value
- * will be negated if it is the closing form of the bracket.
- */
- private static int getBracketType (char ch) {
- switch (ch) {
- case '[': return 1;
- case ']': return -1;
- case '{': return 2;
- case '}': return -2;
- case '(': return 3;
- case ')': return -3;
- default:
- return 0;
- }
- }
-
- private boolean deletePreviousWord() throws IOException {
- StringBuilder killed = new StringBuilder();
- char c;
-
- while (isDelimiter((c = buf.current()))) {
- if (c == 0) {
- break;
- }
-
- killed.append(c);
- backspace();
- }
-
- while (!isDelimiter((c = buf.current()))) {
- if (c == 0) {
- break;
- }
-
- killed.append(c);
- backspace();
- }
-
- String copy = killed.reverse().toString();
- killRing.addBackwards(copy);
- return true;
- }
-
- private boolean deleteNextWord() throws IOException {
- StringBuilder killed = new StringBuilder();
- char c;
-
- while (isDelimiter((c = buf.nextChar()))) {
- if (c == 0) {
- break;
- }
- killed.append(c);
- delete();
- }
-
- while (!isDelimiter((c = buf.nextChar()))) {
- if (c == 0) {
- break;
- }
- killed.append(c);
- delete();
- }
-
- String copy = killed.toString();
- killRing.add(copy);
-
- return true;
- }
-
- private boolean capitalizeWord() throws IOException {
- boolean first = true;
- int i = 1;
- char c;
- while (buf.cursor + i - 1< buf.length() && !isDelimiter((c = buf.buffer.charAt(buf.cursor + i - 1)))) {
- buf.buffer.setCharAt(buf.cursor + i - 1, first ? Character.toUpperCase(c) : Character.toLowerCase(c));
- first = false;
- i++;
- }
- drawBuffer();
- moveCursor(i - 1);
- return true;
- }
-
- private boolean upCaseWord() throws IOException {
- int i = 1;
- char c;
- while (buf.cursor + i - 1 < buf.length() && !isDelimiter((c = buf.buffer.charAt(buf.cursor + i - 1)))) {
- buf.buffer.setCharAt(buf.cursor + i - 1, Character.toUpperCase(c));
- i++;
- }
- drawBuffer();
- moveCursor(i - 1);
- return true;
- }
-
- private boolean downCaseWord() throws IOException {
- int i = 1;
- char c;
- while (buf.cursor + i - 1 < buf.length() && !isDelimiter((c = buf.buffer.charAt(buf.cursor + i - 1)))) {
- buf.buffer.setCharAt(buf.cursor + i - 1, Character.toLowerCase(c));
- i++;
- }
- drawBuffer();
- moveCursor(i - 1);
- return true;
- }
-
- /**
- * Performs character transpose. The character prior to the cursor and the
- * character under the cursor are swapped and the cursor is advanced one
- * character unless you are already at the end of the line.
- *
- * @param count The number of times to perform the transpose
- * @return true if the operation succeeded, false otherwise (e.g. transpose
- * cannot happen at the beginning of the line).
- */
- private boolean transposeChars(int count) throws IOException {
- for (; count > 0; --count) {
- if (buf.cursor == 0 || buf.cursor == buf.buffer.length()) {
- return false;
- }
-
- int first = buf.cursor-1;
- int second = buf.cursor;
-
- char tmp = buf.buffer.charAt (first);
- buf.buffer.setCharAt(first, buf.buffer.charAt(second));
- buf.buffer.setCharAt(second, tmp);
-
- // This could be done more efficiently by only re-drawing at the end.
- moveInternal(-1);
- drawBuffer();
- moveInternal(2);
- }
-
- return true;
- }
-
- public boolean isKeyMap(String name) {
- // Current keymap.
- KeyMap map = consoleKeys.getKeys();
- KeyMap mapByName = consoleKeys.getKeyMaps().get(name);
-
- if (mapByName == null)
- return false;
-
- /*
- * This may not be safe to do, but there doesn't appear to be a
- * clean way to find this information out.
- */
- return map == mapByName;
- }
-
-
- /**
- * The equivalent of hitting <RET>. The line is considered
- * complete and is returned.
- *
- * @return The completed line of text.
- */
- public String accept() throws IOException {
- moveToEnd();
- println(); // output newline
- flush();
- return finishBuffer();
- }
-
- private void abort() throws IOException {
- beep();
- buf.clear();
- println();
- redrawLine();
- }
-
- /**
- * Move the cursor where characters.
- *
- * @param num If less than 0, move abs(where) to the left, otherwise move where to the right.
- * @return The number of spaces we moved
- */
- public int moveCursor(final int num) throws IOException {
- int where = num;
-
- if ((buf.cursor == 0) && (where <= 0)) {
- return 0;
- }
-
- if ((buf.cursor == buf.buffer.length()) && (where >= 0)) {
- return 0;
- }
-
- if ((buf.cursor + where) < 0) {
- where = -buf.cursor;
- }
- else if ((buf.cursor + where) > buf.buffer.length()) {
- where = buf.buffer.length() - buf.cursor;
- }
-
- moveInternal(where);
-
- return where;
- }
-
- /**
- * Move the cursor where characters, without checking the current buffer.
- *
- * @param where the number of characters to move to the right or left.
- */
- private void moveInternal(final int where) throws IOException {
- // debug ("move cursor " + where + " ("
- // + buf.cursor + " => " + (buf.cursor + where) + ")");
- buf.cursor += where;
-
- int i0;
- int i1;
- if (mask == null) {
- if (where < 0) {
- i1 = promptLen + wcwidth(buf.buffer, 0, buf.cursor, promptLen);
- i0 = i1 + wcwidth(buf.buffer, buf.cursor, buf.cursor - where, i1);
- } else {
- i0 = promptLen + wcwidth(buf.buffer, 0, buf.cursor - where, promptLen);
- i1 = i0 + wcwidth(buf.buffer, buf.cursor - where, buf.cursor, i0);
- }
- } else if (mask != NULL_MASK) {
- i1 = promptLen + buf.cursor;
- i0 = i1 - where;
- } else {
- return;
- }
- moveCursorFromTo(i0, i1);
- }
-
- private void moveCursorFromTo(int i0, int i1) throws IOException {
- if (i0 == i1) return;
- int width = getTerminal().getWidth();
- int l0 = i0 / width;
- int c0 = i0 % width;
- int l1 = i1 / width;
- int c1 = i1 % width;
- if (l0 == l1 + 1) {
- if (!tputs("cursor_up")) {
- tputs("parm_up_cursor", 1);
- }
- } else if (l0 > l1) {
- if (!tputs("parm_up_cursor", l0 - l1)) {
- for (int i = l1; i < l0; i++) {
- tputs("cursor_up");
- }
- }
- } else if (l0 < l1) {
- tputs("carriage_return");
- rawPrint('\n', l1 - l0);
- c0 = 0;
- }
- if (c0 == c1 - 1) {
- tputs("cursor_right");
- } else if (c0 == c1 + 1) {
- tputs("cursor_left");
- } else if (c0 < c1) {
- if (!tputs("parm_right_cursor", c1 - c0)) {
- for (int i = c0; i < c1; i++) {
- tputs("cursor_right");
- }
- }
- } else if (c0 > c1) {
- if (!tputs("parm_left_cursor", c0 - c1)) {
- for (int i = c1; i < c0; i++) {
- tputs("cursor_left");
- }
- }
- }
- cursorOk = true;
- }
-
- /**
- * Read a character from the console.
- *
- * @return the character, or -1 if an EOF is received.
- */
- public int readCharacter() throws IOException {
- return readCharacter(false);
- }
-
- /**
- * Read a character from the console. If boolean parameter is "true", it will check whether the keystroke was an "alt-" key combination, and
- * if so add 1000 to the value returned. Better way...?
- *
- * @return the character, or -1 if an EOF is received.
- */
- public int readCharacter(boolean checkForAltKeyCombo) throws IOException {
- int c = reader.read();
- if (c >= 0) {
- Log.trace("Keystroke: ", c);
- // clear any echo characters
- if (terminal.isSupported()) {
- clearEcho(c);
- }
- if (c == ESCAPE && checkForAltKeyCombo && in.peek(escapeTimeout) >= 32) {
- /* When ESC is encountered and there is a pending
- * character in the pushback queue, then it seems to be
- * an Alt-[key] combination. Is this true, cross-platform?
- * It's working for me on Debian GNU/Linux at the moment anyway.
- * I removed the "isNonBlockingEnabled" check, though it was
- * in the similar code in "readLine(String prompt, final Character mask)" (way down),
- * as I am not sure / didn't look up what it's about, and things are working so far w/o it.
- */
- int next = reader.read();
- // with research, there's probably a much cleaner way to do this, but, this is now it flags an Alt key combination for now:
- next = next + 1000;
- return next;
- }
- }
- return c;
- }
-
- /**
- * Clear the echoed characters for the specified character code.
- */
- private int clearEcho(final int c) throws IOException {
- // if the terminal is not echoing, then ignore
- if (!terminal.isEchoEnabled()) {
- return 0;
- }
-
- // otherwise, clear
- int pos = getCursorPosition();
- int num = wcwidth(c, pos);
- moveCursorFromTo(pos + num, pos);
- drawBuffer(num);
-
- return num;
- }
-
- public int readCharacter(final char... allowed) throws IOException {
- return readCharacter(false, allowed);
- }
-
- public int readCharacter(boolean checkForAltKeyCombo, final char... allowed) throws IOException {
- // if we restrict to a limited set and the current character is not in the set, then try again.
- char c;
-
- Arrays.sort(allowed); // always need to sort before binarySearch
-
- while (Arrays.binarySearch(allowed, c = (char) readCharacter(checkForAltKeyCombo)) < 0) {
- // nothing
- }
-
- return c;
- }
-
- /**
- * Read from the input stream and decode an operation from the key map.
- *
- * The input stream will be read character by character until a matching
- * binding can be found. Characters that can't possibly be matched to
- * any binding will be discarded.
- *
- * @param keys the KeyMap to use for decoding the input stream
- * @return the decoded binding or null
if the end of
- * stream has been reached
- */
- public Object readBinding(KeyMap keys) throws IOException {
- Object o;
- opBuffer.setLength(0);
- do {
- int c = pushBackChar.isEmpty() ? readCharacter() : pushBackChar.pop();
- if (c == -1) {
- return null;
- }
- opBuffer.appendCodePoint(c);
-
- if (recording) {
- macro += new String(Character.toChars(c));
- }
-
- if (quotedInsert) {
- o = Operation.SELF_INSERT;
- quotedInsert = false;
- } else {
- o = keys.getBound(opBuffer);
- }
-
- /*
- * The kill ring keeps record of whether or not the
- * previous command was a yank or a kill. We reset
- * that state here if needed.
- */
- if (!recording && !(o instanceof KeyMap)) {
- if (o != Operation.YANK_POP && o != Operation.YANK) {
- killRing.resetLastYank();
- }
- if (o != Operation.KILL_LINE && o != Operation.KILL_WHOLE_LINE
- && o != Operation.BACKWARD_KILL_WORD && o != Operation.KILL_WORD
- && o != Operation.UNIX_LINE_DISCARD && o != Operation.UNIX_WORD_RUBOUT) {
- killRing.resetLastKill();
- }
- }
-
- if (o == Operation.DO_LOWERCASE_VERSION) {
- opBuffer.setLength(opBuffer.length() - 1);
- opBuffer.append(Character.toLowerCase((char) c));
- o = keys.getBound(opBuffer);
- }
-
- /*
- * A KeyMap indicates that the key that was struck has a
- * number of keys that can follow it as indicated in the
- * map. This is used primarily for Emacs style ESC-META-x
- * lookups. Since more keys must follow, go back to waiting
- * for the next key.
- */
- if (o instanceof KeyMap) {
- /*
- * The ESC key (#27) is special in that it is ambiguous until
- * you know what is coming next. The ESC could be a literal
- * escape, like the user entering vi-move mode, or it could
- * be part of a terminal control sequence. The following
- * logic attempts to disambiguate things in the same
- * fashion as regular vi or readline.
- *
- * When ESC is encountered and there is no other pending
- * character in the pushback queue, then attempt to peek
- * into the input stream (if the feature is enabled) for
- * 150ms. If nothing else is coming, then assume it is
- * not a terminal control sequence, but a raw escape.
- */
- if (c == ESCAPE
- && pushBackChar.isEmpty()
- && in.isNonBlockingEnabled()
- && in.peek(escapeTimeout) == READ_EXPIRED) {
- o = ((KeyMap) o).getAnotherKey();
- if (o == null || o instanceof KeyMap) {
- continue;
- }
- opBuffer.setLength(0);
- } else {
- continue;
- }
- }
-
- /*
- * If we didn't find a binding for the key and there is
- * more than one character accumulated then start checking
- * the largest span of characters from the beginning to
- * see if there is a binding for them.
- *
- * For example if our buffer has ESC,CTRL-M,C the getBound()
- * called previously indicated that there is no binding for
- * this sequence, so this then checks ESC,CTRL-M, and failing
- * that, just ESC. Each keystroke that is pealed off the end
- * during these tests is stuffed onto the pushback buffer so
- * they won't be lost.
- *
- * If there is no binding found, then we go back to waiting for
- * input.
- */
- while (o == null && opBuffer.length() > 0) {
- c = opBuffer.charAt(opBuffer.length() - 1);
- opBuffer.setLength(opBuffer.length() - 1);
- Object o2 = keys.getBound(opBuffer);
- if (o2 instanceof KeyMap) {
- o = ((KeyMap) o2).getAnotherKey();
- if (o == null) {
- continue;
- } else {
- pushBackChar.push((char) c);
- }
- }
- }
-
- } while (o == null || o instanceof KeyMap);
-
- return o;
- }
-
- public String getLastBinding() {
- return opBuffer.toString();
- }
-
- //
- // Key Bindings
- //
-
- public static final String JLINE_COMPLETION_THRESHOLD = "jline.completion.threshold";
-
- //
- // Line Reading
- //
-
- /**
- * Read the next line and return the contents of the buffer.
- */
- public String readLine() throws IOException {
- return readLine((String) null);
- }
-
- /**
- * Read the next line with the specified character mask. If null, then
- * characters will be echoed. If 0, then no characters will be echoed.
- */
- public String readLine(final Character mask) throws IOException {
- return readLine(null, mask);
- }
-
- public String readLine(final String prompt) throws IOException {
- return readLine(prompt, null);
- }
-
- /**
- * Read a line from the in {@link InputStream}, and return the line
- * (without any trailing newlines).
- *
- * @param prompt The prompt to issue to the console, may be null.
- * @return A line that is read from the terminal, or null if there was null input (e.g., CTRL-D
- * was pressed).
- */
- public String readLine(String prompt, final Character mask) throws IOException {
- return readLine(prompt, mask, null);
- }
-
- /**
- * Sets the current keymap by name. Supported keymaps are "emacs",
- * "vi-insert", "vi-move".
- * @param name The name of the keymap to switch to
- * @return true if the keymap was set, or false if the keymap is
- * not recognized.
- */
- public boolean setKeyMap(String name) {
- return consoleKeys.setKeyMap(name);
- }
-
- /**
- * Returns the name of the current key mapping.
- * @return the name of the key mapping. This will be the canonical name
- * of the current mode of the key map and may not reflect the name that
- * was used with {@link #setKeyMap(String)}.
- */
- public String getKeyMap() {
- return consoleKeys.getKeys().getName();
- }
-
- /**
- * Read a line from the in {@link InputStream}, and return the line
- * (without any trailing newlines).
- *
- * @param prompt The prompt to issue to the console, may be null.
- * @return A line that is read from the terminal, or null if there was null input (e.g., CTRL-D
- * was pressed).
- */
- public String readLine(String prompt, final Character mask, String buffer) throws IOException {
- // prompt may be null
- // mask may be null
- // buffer may be null
-
- /*
- * This is the accumulator for VI-mode repeat count. That is, while in
- * move mode, if you type 30x it will delete 30 characters. This is
- * where the "30" is accumulated until the command is struck.
- */
- int repeatCount = 0;
-
- // FIXME: This blows, each call to readLine will reset the console's state which doesn't seem very nice.
- this.mask = mask != null ? mask : this.echoCharacter;
- if (prompt != null) {
- setPrompt(prompt);
- }
- else {
- prompt = getPrompt();
- }
-
- try {
- if (buffer != null) {
- buf.write(buffer);
- }
-
- if (!terminal.isSupported()) {
- beforeReadLine(prompt, mask);
- }
-
- if (buffer != null && buffer.length() > 0
- || prompt != null && prompt.length() > 0) {
- drawLine();
- out.flush();
- }
-
- if (terminal.isAnsiSupported() && System.console() != null) {
- //detect the prompt length by reading the cursor position from the terminal
- //the real prompt length could differ from the simple prompt length due to
- //use of escape sequences:
- out.write("\033[6n");
- out.flush();
- StringBuilder input = new StringBuilder();
- while (true) {
- int read;
- while ((read = in.read()) != 'R') {
- input.appendCodePoint(read);
- }
- input.appendCodePoint(read);
- Matcher m = CURSOR_COLUMN_PATTERN.matcher(input);
- if (m.matches()) {
- promptLen = Integer.parseInt(m.group("column")) - 1;
- String prefix = m.group("prefix");
- List chars = new ArrayList<>();
- for (int i = prefix.length() - 1; i >= 0; i--) {
- chars.add(prefix.charAt(i));
- }
- pushBackChar.addAll(0, chars);
- break;
- }
- }
- }
-
- // if the terminal is unsupported, just use plain-java reading
- if (!terminal.isSupported()) {
- return readLineSimple();
- }
-
- if (handleUserInterrupt) {
- terminal.disableInterruptCharacter();
- }
- if (handleLitteralNext && (terminal instanceof UnixTerminal)) {
- ((UnixTerminal) terminal).disableLitteralNextCharacter();
- }
-
- String originalPrompt = this.prompt;
-
- state = State.NORMAL;
-
- boolean success = true;
-
- while (true) {
-
- Object o = readBinding(getKeys());
- if (o == null) {
- return null;
- }
- int c = 0;
- if (opBuffer.length() > 0) {
- c = opBuffer.codePointBefore(opBuffer.length());
- }
- Log.trace("Binding: ", o);
-
-
- // Handle macros
- if (o instanceof String) {
- String macro = (String) o;
- for (int i = 0; i < macro.length(); i++) {
- pushBackChar.push(macro.charAt(macro.length() - 1 - i));
- }
- opBuffer.setLength(0);
- continue;
- }
-
- // Handle custom callbacks
- //original code:
-// if (o instanceof ActionListener) {
-// ((ActionListener) o).actionPerformed(null);
-// sb.setLength( 0 );
-// continue;
-// }
- //using reflection to avoid dependency on java.desktop:
- try {
- Class> actionListener =
- Class.forName("java.awt.event.ActionListener", false, ClassLoader.getSystemClassLoader());
- Class> actionEvent =
- Class.forName("java.awt.event.ActionEvent", false, ClassLoader.getSystemClassLoader());
- if (actionListener.isAssignableFrom(o.getClass())) {
- Method actionPerformed =
- actionListener.getMethod("actionPerformed", actionEvent);
- try {
- actionPerformed.invoke(o, (Object) null);
- } catch (InvocationTargetException ex ) {
- Log.error("Exception while running registered action", ex);
- }
- opBuffer.setLength(0);
- continue;
- }
- } catch (ReflectiveOperationException ex) {
- //ignore
- }
-
- if (o instanceof Runnable) {
- ((Runnable) o).run();
- opBuffer.setLength(0);
- continue;
- }
-
- CursorBuffer oldBuf = new CursorBuffer();
- oldBuf.buffer.append(buf.buffer);
- oldBuf.cursor = buf.cursor;
-
- // Search mode.
- //
- // Note that we have to do this first, because if there is a command
- // not linked to a search command, we leave the search mode and fall
- // through to the normal state.
- if (state == State.SEARCH || state == State.FORWARD_SEARCH) {
- int cursorDest = -1;
- // TODO: check the isearch-terminators variable terminating the search
- switch ( ((Operation) o )) {
- case ABORT:
- state = State.NORMAL;
- buf.clear();
- buf.write(originalBuffer.buffer);
- buf.cursor = originalBuffer.cursor;
- break;
-
- case REVERSE_SEARCH_HISTORY:
- state = State.SEARCH;
- if (searchTerm.length() == 0) {
- searchTerm.append(previousSearchTerm);
- }
-
- if (searchIndex > 0) {
- searchIndex = searchBackwards(searchTerm.toString(), searchIndex);
- }
- break;
-
- case FORWARD_SEARCH_HISTORY:
- state = State.FORWARD_SEARCH;
- if (searchTerm.length() == 0) {
- searchTerm.append(previousSearchTerm);
- }
-
- if (searchIndex > -1 && searchIndex < history.size() - 1) {
- searchIndex = searchForwards(searchTerm.toString(), searchIndex);
- }
- break;
-
- case BACKWARD_DELETE_CHAR:
- if (searchTerm.length() > 0) {
- searchTerm.deleteCharAt(searchTerm.length() - 1);
- if (state == State.SEARCH) {
- searchIndex = searchBackwards(searchTerm.toString());
- } else {
- searchIndex = searchForwards(searchTerm.toString());
- }
- }
- break;
-
- case SELF_INSERT:
- searchTerm.appendCodePoint(c);
- if (state == State.SEARCH) {
- searchIndex = searchBackwards(searchTerm.toString());
- } else {
- searchIndex = searchForwards(searchTerm.toString());
- }
- break;
-
- default:
- // Set buffer and cursor position to the found string.
- if (searchIndex != -1) {
- history.moveTo(searchIndex);
- // set cursor position to the found string
- cursorDest = history.current().toString().indexOf(searchTerm.toString());
- }
- if (o != Operation.ACCEPT_LINE) {
- o = null;
- }
- state = State.NORMAL;
- break;
- }
-
- // if we're still in search mode, print the search status
- if (state == State.SEARCH || state == State.FORWARD_SEARCH) {
- if (searchTerm.length() == 0) {
- if (state == State.SEARCH) {
- printSearchStatus("", "");
- } else {
- printForwardSearchStatus("", "");
- }
- searchIndex = -1;
- } else {
- if (searchIndex == -1) {
- beep();
- printSearchStatus(searchTerm.toString(), "");
- } else if (state == State.SEARCH) {
- printSearchStatus(searchTerm.toString(), history.get(searchIndex).toString());
- } else {
- printForwardSearchStatus(searchTerm.toString(), history.get(searchIndex).toString());
- }
- }
- }
- // otherwise, restore the line
- else {
- restoreLine(originalPrompt, cursorDest);
- }
- }
- if (state != State.SEARCH && state != State.FORWARD_SEARCH) {
- /*
- * If this is still false at the end of the switch, then
- * we reset our repeatCount to 0.
- */
- boolean isArgDigit = false;
-
- /*
- * Every command that can be repeated a specified number
- * of times, needs to know how many times to repeat, so
- * we figure that out here.
- */
- int count = (repeatCount == 0) ? 1 : repeatCount;
-
- /*
- * Default success to true. You only need to explicitly
- * set it if something goes wrong.
- */
- success = true;
-
- if (o instanceof Operation) {
- Operation op = (Operation)o;
- /*
- * Current location of the cursor (prior to the operation).
- * These are used by vi *-to operation (e.g. delete-to)
- * so we know where we came from.
- */
- int cursorStart = buf.cursor;
- State origState = state;
-
- /*
- * If we are on a "vi" movement based operation, then we
- * need to restrict the sets of inputs pretty heavily.
- */
- if (state == State.VI_CHANGE_TO
- || state == State.VI_YANK_TO
- || state == State.VI_DELETE_TO) {
-
- op = viDeleteChangeYankToRemap(op);
- }
-
- switch ( op ) {
- case COMPLETE: // tab
- // There is an annoyance with tab completion in that
- // sometimes the user is actually pasting input in that
- // has physical tabs in it. This attempts to look at how
- // quickly a character follows the tab, if the character
- // follows *immediately*, we assume it is a tab literal.
- boolean isTabLiteral = false;
- if (copyPasteDetection
- && c == 9
- && (!pushBackChar.isEmpty()
- || (in.isNonBlockingEnabled() && in.peek(escapeTimeout) != -2))) {
- isTabLiteral = true;
- }
-
- if (! isTabLiteral) {
- success = complete();
- }
- else {
- putString(opBuffer);
- }
- break;
-
- case POSSIBLE_COMPLETIONS:
- printCompletionCandidates();
- break;
-
- case BEGINNING_OF_LINE:
- success = setCursorPosition(0);
- break;
-
- case YANK:
- success = yank();
- break;
-
- case YANK_POP:
- success = yankPop();
- break;
-
- case KILL_LINE: // CTRL-K
- success = killLine();
- break;
-
- case KILL_WHOLE_LINE:
- success = setCursorPosition(0) && killLine();
- break;
-
- case CLEAR_SCREEN: // CTRL-L
- success = clearScreen();
- redrawLine();
- break;
-
- case OVERWRITE_MODE:
- buf.setOverTyping(!buf.isOverTyping());
- break;
-
- case SELF_INSERT:
- putString(opBuffer);
- break;
-
- case ACCEPT_LINE:
- return accept();
-
- case ABORT:
- if (searchTerm == null) {
- abort();
- }
- break;
-
- case INTERRUPT:
- if (handleUserInterrupt) {
- println();
- flush();
- String partialLine = buf.buffer.toString();
- buf.clear();
- history.moveToEnd();
- throw new UserInterruptException(partialLine);
- }
- break;
-
- /*
- * VI_MOVE_ACCEPT_LINE is the result of an ENTER
- * while in move mode. This is the same as a normal
- * ACCEPT_LINE, except that we need to enter
- * insert mode as well.
- */
- case VI_MOVE_ACCEPT_LINE:
- consoleKeys.setKeyMap(KeyMap.VI_INSERT);
- return accept();
-
- case BACKWARD_WORD:
- success = previousWord();
- break;
-
- case FORWARD_WORD:
- success = nextWord();
- break;
-
- case PREVIOUS_HISTORY:
- success = moveHistory(false);
- break;
-
- /*
- * According to bash/readline move through history
- * in "vi" mode will move the cursor to the
- * start of the line. If there is no previous
- * history, then the cursor doesn't move.
- */
- case VI_PREVIOUS_HISTORY:
- success = moveHistory(false, count)
- && setCursorPosition(0);
- break;
-
- case NEXT_HISTORY:
- success = moveHistory(true);
- break;
-
- /*
- * According to bash/readline move through history
- * in "vi" mode will move the cursor to the
- * start of the line. If there is no next history,
- * then the cursor doesn't move.
- */
- case VI_NEXT_HISTORY:
- success = moveHistory(true, count)
- && setCursorPosition(0);
- break;
-
- case BACKWARD_DELETE_CHAR: // backspace
- success = backspace();
- break;
-
- case EXIT_OR_DELETE_CHAR:
- if (buf.buffer.length() == 0) {
- return null;
- }
- success = deleteCurrentCharacter();
- break;
-
- case DELETE_CHAR: // delete
- success = deleteCurrentCharacter();
- break;
-
- case BACKWARD_CHAR:
- success = moveCursor(-(count)) != 0;
- break;
-
- case FORWARD_CHAR:
- success = moveCursor(count) != 0;
- break;
-
- case UNIX_LINE_DISCARD:
- success = resetLine();
- break;
-
- case UNIX_WORD_RUBOUT:
- success = unixWordRubout(count);
- break;
-
- case BACKWARD_KILL_WORD:
- success = deletePreviousWord();
- break;
-
- case KILL_WORD:
- success = deleteNextWord();
- break;
-
- case BEGINNING_OF_HISTORY:
- success = history.moveToFirst();
- if (success) {
- setBuffer(history.current());
- }
- break;
-
- case END_OF_HISTORY:
- success = history.moveToLast();
- if (success) {
- setBuffer(history.current());
- }
- break;
-
- case HISTORY_SEARCH_BACKWARD:
- searchTerm = new StringBuffer(buf.upToCursor());
- searchIndex = searchBackwards(searchTerm.toString(), history.index(), true);
-
- if (searchIndex == -1) {
- beep();
- } else {
- // Maintain cursor position while searching.
- success = history.moveTo(searchIndex);
- if (success) {
- setBufferKeepPos(history.current());
- }
- }
- break;
-
- case HISTORY_SEARCH_FORWARD:
- searchTerm = new StringBuffer(buf.upToCursor());
- int index = history.index() + 1;
-
- if (index == history.size()) {
- history.moveToEnd();
- setBufferKeepPos(searchTerm.toString());
- } else if (index < history.size()) {
- searchIndex = searchForwards(searchTerm.toString(), index, true);
- if (searchIndex == -1) {
- beep();
- } else {
- // Maintain cursor position while searching.
- success = history.moveTo(searchIndex);
- if (success) {
- setBufferKeepPos(history.current());
- }
- }
- }
- break;
-
- case REVERSE_SEARCH_HISTORY:
- originalBuffer = new CursorBuffer();
- originalBuffer.write(buf.buffer);
- originalBuffer.cursor = buf.cursor;
- if (searchTerm != null) {
- previousSearchTerm = searchTerm.toString();
- }
- searchTerm = new StringBuffer(buf.buffer);
- state = State.SEARCH;
- if (searchTerm.length() > 0) {
- searchIndex = searchBackwards(searchTerm.toString());
- if (searchIndex == -1) {
- beep();
- }
- printSearchStatus(searchTerm.toString(),
- searchIndex > -1 ? history.get(searchIndex).toString() : "");
- } else {
- searchIndex = -1;
- printSearchStatus("", "");
- }
- break;
-
- case FORWARD_SEARCH_HISTORY:
- originalBuffer = new CursorBuffer();
- originalBuffer.write(buf.buffer);
- originalBuffer.cursor = buf.cursor;
- if (searchTerm != null) {
- previousSearchTerm = searchTerm.toString();
- }
- searchTerm = new StringBuffer(buf.buffer);
- state = State.FORWARD_SEARCH;
- if (searchTerm.length() > 0) {
- searchIndex = searchForwards(searchTerm.toString());
- if (searchIndex == -1) {
- beep();
- }
- printForwardSearchStatus(searchTerm.toString(),
- searchIndex > -1 ? history.get(searchIndex).toString() : "");
- } else {
- searchIndex = -1;
- printForwardSearchStatus("", "");
- }
- break;
-
- case CAPITALIZE_WORD:
- success = capitalizeWord();
- break;
-
- case UPCASE_WORD:
- success = upCaseWord();
- break;
-
- case DOWNCASE_WORD:
- success = downCaseWord();
- break;
-
- case END_OF_LINE:
- success = moveToEnd();
- break;
-
- case TAB_INSERT:
- putString( "\t" );
- break;
-
- case RE_READ_INIT_FILE:
- consoleKeys.loadKeys(appName, inputrcUrl);
- break;
-
- case START_KBD_MACRO:
- recording = true;
- break;
-
- case END_KBD_MACRO:
- recording = false;
- macro = macro.substring(0, macro.length() - opBuffer.length());
- break;
-
- case CALL_LAST_KBD_MACRO:
- for (int i = 0; i < macro.length(); i++) {
- pushBackChar.push(macro.charAt(macro.length() - 1 - i));
- }
- opBuffer.setLength(0);
- break;
-
- case VI_EDITING_MODE:
- consoleKeys.setKeyMap(KeyMap.VI_INSERT);
- break;
-
- case VI_MOVEMENT_MODE:
- /*
- * If we are re-entering move mode from an
- * aborted yank-to, delete-to, change-to then
- * don't move the cursor back. The cursor is
- * only move on an expclit entry to movement
- * mode.
- */
- if (state == State.NORMAL) {
- moveCursor(-1);
- }
- consoleKeys.setKeyMap(KeyMap.VI_MOVE);
- break;
-
- case VI_INSERTION_MODE:
- consoleKeys.setKeyMap(KeyMap.VI_INSERT);
- break;
-
- case VI_APPEND_MODE:
- moveCursor(1);
- consoleKeys.setKeyMap(KeyMap.VI_INSERT);
- break;
-
- case VI_APPEND_EOL:
- success = moveToEnd();
- consoleKeys.setKeyMap(KeyMap.VI_INSERT);
- break;
-
- /*
- * Handler for CTRL-D. Attempts to follow readline
- * behavior. If the line is empty, then it is an EOF
- * otherwise it is as if the user hit enter.
- */
- case VI_EOF_MAYBE:
- if (buf.buffer.length() == 0) {
- return null;
- }
- return accept();
-
- case TRANSPOSE_CHARS:
- success = transposeChars(count);
- break;
-
- case INSERT_COMMENT:
- return insertComment (false);
-
- case INSERT_CLOSE_CURLY:
- insertClose("}");
- break;
-
- case INSERT_CLOSE_PAREN:
- insertClose(")");
- break;
-
- case INSERT_CLOSE_SQUARE:
- insertClose("]");
- break;
-
- case VI_INSERT_COMMENT:
- return insertComment (true);
-
- case VI_MATCH:
- success = viMatch ();
- break;
-
- case VI_SEARCH:
- int lastChar = viSearch(opBuffer.charAt(0));
- if (lastChar != -1) {
- pushBackChar.push((char)lastChar);
- }
- break;
-
- case VI_ARG_DIGIT:
- repeatCount = (repeatCount * 10) + opBuffer.charAt(0) - '0';
- isArgDigit = true;
- break;
-
- case VI_BEGINNING_OF_LINE_OR_ARG_DIGIT:
- if (repeatCount > 0) {
- repeatCount = (repeatCount * 10) + opBuffer.charAt(0) - '0';
- isArgDigit = true;
- }
- else {
- success = setCursorPosition(0);
- }
- break;
-
- case VI_FIRST_PRINT:
- success = setCursorPosition(0) && viNextWord(1);
- break;
-
- case VI_PREV_WORD:
- success = viPreviousWord(count);
- break;
-
- case VI_NEXT_WORD:
- success = viNextWord(count);
- break;
-
- case VI_END_WORD:
- success = viEndWord(count);
- break;
-
- case VI_INSERT_BEG:
- success = setCursorPosition(0);
- consoleKeys.setKeyMap(KeyMap.VI_INSERT);
- break;
-
- case VI_RUBOUT:
- success = viRubout(count);
- break;
-
- case VI_DELETE:
- success = viDelete(count);
- break;
-
- case VI_DELETE_TO:
- /*
- * This is a weird special case. In vi
- * "dd" deletes the current line. So if we
- * get a delete-to, followed by a delete-to,
- * we delete the line.
- */
- if (state == State.VI_DELETE_TO) {
- success = setCursorPosition(0) && killLine();
- state = origState = State.NORMAL;
- }
- else {
- state = State.VI_DELETE_TO;
- }
- break;
-
- case VI_YANK_TO:
- // Similar to delete-to, a "yy" yanks the whole line.
- if (state == State.VI_YANK_TO) {
- yankBuffer = buf.buffer.toString();
- state = origState = State.NORMAL;
- }
- else {
- state = State.VI_YANK_TO;
- }
- break;
-
- case VI_CHANGE_TO:
- if (state == State.VI_CHANGE_TO) {
- success = setCursorPosition(0) && killLine();
- state = origState = State.NORMAL;
- consoleKeys.setKeyMap(KeyMap.VI_INSERT);
- }
- else {
- state = State.VI_CHANGE_TO;
- }
- break;
-
- case VI_KILL_WHOLE_LINE:
- success = setCursorPosition(0) && killLine();
- consoleKeys.setKeyMap(KeyMap.VI_INSERT);
- break;
-
- case VI_PUT:
- success = viPut(count);
- break;
-
- case VI_CHAR_SEARCH: {
- // ';' and ',' don't need another character. They indicate repeat next or repeat prev.
- int searchChar = (c != ';' && c != ',')
- ? (pushBackChar.isEmpty()
- ? readCharacter()
- : pushBackChar.pop ())
- : 0;
-
- success = viCharSearch(count, c, searchChar);
- }
- break;
-
- case VI_CHANGE_CASE:
- success = viChangeCase(count);
- break;
-
- case VI_CHANGE_CHAR:
- success = viChangeChar(count,
- pushBackChar.isEmpty()
- ? readCharacter()
- : pushBackChar.pop());
- break;
-
- case VI_DELETE_TO_EOL:
- success = viDeleteTo(buf.cursor, buf.buffer.length(), false);
- break;
-
- case VI_CHANGE_TO_EOL:
- success = viDeleteTo(buf.cursor, buf.buffer.length(), true);
- consoleKeys.setKeyMap(KeyMap.VI_INSERT);
- break;
-
- case EMACS_EDITING_MODE:
- consoleKeys.setKeyMap(KeyMap.EMACS);
- break;
-
- case QUIT:
- getCursorBuffer().clear();
- return accept();
-
- case QUOTED_INSERT:
- quotedInsert = true;
- break;
-
- case PASTE_FROM_CLIPBOARD:
-// paste();
- break;
-
- default:
- break;
- }
-
- /*
- * If we were in a yank-to, delete-to, move-to
- * when this operation started, then fall back to
- */
- if (origState != State.NORMAL) {
- if (origState == State.VI_DELETE_TO) {
- success = viDeleteTo(cursorStart, buf.cursor, false);
- }
- else if (origState == State.VI_CHANGE_TO) {
- success = viDeleteTo(cursorStart, buf.cursor, true);
- consoleKeys.setKeyMap(KeyMap.VI_INSERT);
- }
- else if (origState == State.VI_YANK_TO) {
- success = viYankTo(cursorStart, buf.cursor);
- }
- state = State.NORMAL;
- }
-
- /*
- * Another subtly. The check for the NORMAL state is
- * to ensure that we do not clear out the repeat
- * count when in delete-to, yank-to, or move-to modes.
- */
- if (state == State.NORMAL && !isArgDigit) {
- /*
- * If the operation performed wasn't a vi argument
- * digit, then clear out the current repeatCount;
- */
- repeatCount = 0;
- }
-
- if (state != State.SEARCH && state != State.FORWARD_SEARCH) {
- originalBuffer = null;
- previousSearchTerm = "";
- searchTerm = null;
- searchIndex = -1;
- }
- }
- }
- if (!success) {
- beep();
- }
- opBuffer.setLength(0);
-
- flush();
- }
- }
- finally {
- if (!terminal.isSupported()) {
- afterReadLine();
- }
- if (handleUserInterrupt) {
- terminal.enableInterruptCharacter();
- }
- }
- }
- //where:
- private Pattern CURSOR_COLUMN_PATTERN =
- Pattern.compile("(?.*)\033\\[[0-9]+;(?[0-9]+)R", Pattern.DOTALL);
-
- /**
- * Read a line for unsupported terminals.
- */
- private String readLineSimple() throws IOException {
-
- if (skipLF) {
- skipLF = false;
-
- int i = readCharacter();
-
- if (i == -1 || i == '\r') {
- return finishBuffer();
- } else if (i == '\n') {
- // ignore
- } else {
- buf.buffer.append((char) i);
- }
- }
-
- while (true) {
- int i = readCharacter();
-
- if (i == -1 && buf.buffer.length() == 0) {
- return null;
- }
-
- if (i == -1 || i == '\n') {
- return finishBuffer();
- } else if (i == '\r') {
- skipLF = true;
- return finishBuffer();
- } else {
- buf.buffer.append((char) i);
- }
- }
- }
-
- //
- // Completion
- //
-
- private final List completers = new LinkedList();
-
- private CompletionHandler completionHandler = new CandidateListCompletionHandler();
-
- /**
- * Add the specified {@link jline.console.completer.Completer} to the list of handlers for tab-completion.
- *
- * @param completer the {@link jline.console.completer.Completer} to add
- * @return true if it was successfully added
- */
- public boolean addCompleter(final Completer completer) {
- return completers.add(completer);
- }
-
- /**
- * Remove the specified {@link jline.console.completer.Completer} from the list of handlers for tab-completion.
- *
- * @param completer The {@link Completer} to remove
- * @return True if it was successfully removed
- */
- public boolean removeCompleter(final Completer completer) {
- return completers.remove(completer);
- }
-
- /**
- * Returns an unmodifiable list of all the completers.
- */
- public Collection getCompleters() {
- return Collections.unmodifiableList(completers);
- }
-
- public void setCompletionHandler(final CompletionHandler handler) {
- this.completionHandler = checkNotNull(handler);
- }
-
- public CompletionHandler getCompletionHandler() {
- return this.completionHandler;
- }
-
- /**
- * Use the completers to modify the buffer with the appropriate completions.
- *
- * @return true if successful
- */
- protected boolean complete() throws IOException {
- // debug ("tab for (" + buf + ")");
- if (completers.size() == 0) {
- return false;
- }
-
- List candidates = new LinkedList();
- String bufstr = buf.buffer.toString();
- int cursor = buf.cursor;
-
- int position = -1;
-
- for (Completer comp : completers) {
- if ((position = comp.complete(bufstr, cursor, candidates)) != -1) {
- break;
- }
- }
-
- return candidates.size() != 0 && getCompletionHandler().complete(this, candidates, position);
- }
-
- protected void printCompletionCandidates() throws IOException {
- // debug ("tab for (" + buf + ")");
- if (completers.size() == 0) {
- return;
- }
-
- List candidates = new LinkedList();
- String bufstr = buf.buffer.toString();
- int cursor = buf.cursor;
-
- for (Completer comp : completers) {
- if (comp.complete(bufstr, cursor, candidates) != -1) {
- break;
- }
- }
- CandidateListCompletionHandler.printCandidates(this, candidates);
- drawLine();
- }
-
- /**
- * The number of tab-completion candidates above which a warning will be
- * prompted before showing all the candidates.
- */
- private int autoprintThreshold = Configuration.getInteger(JLINE_COMPLETION_THRESHOLD, 100); // same default as bash
-
- /**
- * @param threshold the number of candidates to print without issuing a warning.
- */
- public void setAutoprintThreshold(final int threshold) {
- this.autoprintThreshold = threshold;
- }
-
- /**
- * @return the number of candidates to print without issuing a warning.
- */
- public int getAutoprintThreshold() {
- return autoprintThreshold;
- }
-
- private boolean paginationEnabled;
-
- /**
- * Whether to use pagination when the number of rows of candidates exceeds the height of the terminal.
- */
- public void setPaginationEnabled(final boolean enabled) {
- this.paginationEnabled = enabled;
- }
-
- /**
- * Whether to use pagination when the number of rows of candidates exceeds the height of the terminal.
- */
- public boolean isPaginationEnabled() {
- return paginationEnabled;
- }
-
- //
- // History
- //
-
- private History history = new MemoryHistory();
-
- public void setHistory(final History history) {
- this.history = history;
- }
-
- public History getHistory() {
- return history;
- }
-
- private boolean historyEnabled = true;
-
- /**
- * Whether or not to add new commands to the history buffer.
- */
- public void setHistoryEnabled(final boolean enabled) {
- this.historyEnabled = enabled;
- }
-
- /**
- * Whether or not to add new commands to the history buffer.
- */
- public boolean isHistoryEnabled() {
- return historyEnabled;
- }
-
- /**
- * Used in "vi" mode for argumented history move, to move a specific
- * number of history entries forward or back.
- *
- * @param next If true, move forward
- * @param count The number of entries to move
- * @return true if the move was successful
- */
- private boolean moveHistory(final boolean next, int count) throws IOException {
- boolean ok = true;
- for (int i = 0; i < count && (ok = moveHistory(next)); i++) {
- /* empty */
- }
- return ok;
- }
-
- /**
- * Move up or down the history tree.
- */
- private boolean moveHistory(final boolean next) throws IOException {
- if (next && !history.next()) {
- return false;
- }
- else if (!next && !history.previous()) {
- return false;
- }
-
- setBuffer(history.current());
-
- return true;
- }
-
- //
- // Printing
- //
-
- /**
- * Output the specified characters to the output stream without manipulating the current buffer.
- */
- private int fmtPrint(final CharSequence buff, int cursorPos) throws IOException {
- return fmtPrint(buff, 0, buff.length(), cursorPos);
- }
-
- private int fmtPrint(final CharSequence buff, int start, int end) throws IOException {
- return fmtPrint(buff, start, end, getCursorPosition());
- }
-
- private int fmtPrint(final CharSequence buff, int start, int end, int cursorPos) throws IOException {
- checkNotNull(buff);
- for (int i = start; i < end; i++) {
- char c = buff.charAt(i);
- if (c == '\t') {
- int nb = nextTabStop(cursorPos);
- cursorPos += nb;
- while (nb-- > 0) {
- out.write(' ');
- }
- } else if (c < 32) {
- out.write('^');
- out.write((char) (c + '@'));
- cursorPos += 2;
- } else {
- int w = WCWidth.wcwidth(c);
- if (w > 0) {
- out.write(c);
- cursorPos += w;
- }
- }
- }
- cursorOk = false;
- return cursorPos;
- }
-
- /**
- * Output the specified string to the output stream (but not the buffer).
- */
- public void print(final CharSequence s) throws IOException {
- rawPrint(s.toString());
- }
-
- public void println(final CharSequence s) throws IOException {
- print(s);
- println();
- }
-
- private static final String LINE_SEPARATOR = System.getProperty("line.separator");
-
- /**
- * Output a platform-dependent newline.
- */
- public void println() throws IOException {
- rawPrint(LINE_SEPARATOR);
- }
-
- /**
- * Raw output printing
- */
- final void rawPrint(final int c) throws IOException {
- out.write(c);
- cursorOk = false;
- }
-
- final void rawPrint(final String str) throws IOException {
- out.write(str);
- cursorOk = false;
- }
-
- private void rawPrint(final char c, final int num) throws IOException {
- for (int i = 0; i < num; i++) {
- rawPrint(c);
- }
- }
-
- private void rawPrintln(final String s) throws IOException {
- rawPrint(s);
- println();
- }
-
-
- //
- // Actions
- //
-
- /**
- * Issue a delete.
- *
- * @return true if successful
- */
- public boolean delete() throws IOException {
- if (buf.cursor == buf.buffer.length()) {
- return false;
- }
-
- buf.buffer.delete(buf.cursor, buf.cursor + 1);
- drawBuffer(1);
-
- return true;
- }
-
- /**
- * Kill the buffer ahead of the current cursor position.
- *
- * @return true if successful
- */
- public boolean killLine() throws IOException {
- int cp = buf.cursor;
- int len = buf.buffer.length();
-
- if (cp >= len) {
- return false;
- }
-
- int num = len - cp;
- int pos = getCursorPosition();
- int width = wcwidth(buf.buffer, cp, len, pos);
- clearAhead(width, pos);
-
- char[] killed = new char[num];
- buf.buffer.getChars(cp, (cp + num), killed, 0);
- buf.buffer.delete(cp, (cp + num));
-
- String copy = new String(killed);
- killRing.add(copy);
-
- return true;
- }
-
- public boolean yank() throws IOException {
- String yanked = killRing.yank();
-
- if (yanked == null) {
- return false;
- }
- putString(yanked);
- return true;
- }
-
- public boolean yankPop() throws IOException {
- if (!killRing.lastYank()) {
- return false;
- }
- String current = killRing.yank();
- if (current == null) {
- // This shouldn't happen.
- return false;
- }
- backspace(current.length());
- String yanked = killRing.yankPop();
- if (yanked == null) {
- // This shouldn't happen.
- return false;
- }
-
- putString(yanked);
- return true;
- }
-
- /**
- * Clear the screen by issuing the ANSI "clear screen" code.
- */
- public boolean clearScreen() throws IOException {
- if (!tputs("clear_screen")) {
- println();
- }
- return true;
- }
-
- /**
- * Issue an audible keyboard bell.
- */
- public void beep() throws IOException {
- if (bellEnabled) {
- if (tputs("bell")) {
- // need to flush so the console actually beeps
- flush();
- }
- }
- }
-
- //disabled to avoid dependency on java.desktop:
-// /**
-// * Paste the contents of the clipboard into the console buffer
-// *
-// * @return true if clipboard contents pasted
-// */
-// public boolean paste() throws IOException {
-// Clipboard clipboard;
-// try { // May throw ugly exception on system without X
-// clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
-// }
-// catch (Exception e) {
-// return false;
-// }
-//
-// if (clipboard == null) {
-// return false;
-// }
-//
-// Transferable transferable = clipboard.getContents(null);
-//
-// if (transferable == null) {
-// return false;
-// }
-//
-// try {
-// @SuppressWarnings("deprecation")
-// Object content = transferable.getTransferData(DataFlavor.plainTextFlavor);
-//
-// // This fix was suggested in bug #1060649 at
-// // http://sourceforge.net/tracker/index.php?func=detail&aid=1060649&group_id=64033&atid=506056
-// // to get around the deprecated DataFlavor.plainTextFlavor, but it
-// // raises a UnsupportedFlavorException on Mac OS X
-//
-// if (content == null) {
-// try {
-// content = new DataFlavor().getReaderForText(transferable);
-// }
-// catch (Exception e) {
-// // ignore
-// }
-// }
-//
-// if (content == null) {
-// return false;
-// }
-//
-// String value;
-//
-// if (content instanceof Reader) {
-// // TODO: we might want instead connect to the input stream
-// // so we can interpret individual lines
-// value = "";
-// String line;
-//
-// BufferedReader read = new BufferedReader((Reader) content);
-// while ((line = read.readLine()) != null) {
-// if (value.length() > 0) {
-// value += "\n";
-// }
-//
-// value += line;
-// }
-// }
-// else {
-// value = content.toString();
-// }
-//
-// if (value == null) {
-// return true;
-// }
-//
-// putString(value);
-//
-// return true;
-// }
-// catch (UnsupportedFlavorException e) {
-// Log.error("Paste failed: ", e);
-//
-// return false;
-// }
-// }
-
- //disabled to avoid dependency on java.desktop:
-// /**
-// * Adding a triggered Action allows to give another curse of action if a character passed the pre-processing.
-// *
-// * Say you want to close the application if the user enter q.
-// * addTriggerAction('q', new ActionListener(){ System.exit(0); }); would do the trick.
-// */
-// public void addTriggeredAction(final char c, final ActionListener listener) {
-// getKeys().bind(Character.toString(c), listener);
-// }
-
- //
- // Formatted Output
- //
-
- /**
- * Output the specified {@link Collection} in proper columns.
- */
- public void printColumns(final Collection extends CharSequence> items) throws IOException {
- if (items == null || items.isEmpty()) {
- return;
- }
-
- int width = getTerminal().getWidth();
- int height = getTerminal().getHeight();
-
- int maxWidth = 0;
- for (CharSequence item : items) {
- // we use 0 here, as we don't really support tabulations inside candidates
- int len = wcwidth(Ansi.stripAnsi(item.toString()), 0);
- maxWidth = Math.max(maxWidth, len);
- }
- maxWidth = maxWidth + 3;
- Log.debug("Max width: ", maxWidth);
-
- int showLines;
- if (isPaginationEnabled()) {
- showLines = height - 1; // page limit
- }
- else {
- showLines = Integer.MAX_VALUE;
- }
-
- StringBuilder buff = new StringBuilder();
- int realLength = 0;
- for (CharSequence item : items) {
- if ((realLength + maxWidth) > width) {
- rawPrintln(buff.toString());
- buff.setLength(0);
- realLength = 0;
-
- if (--showLines == 0) {
- // Overflow
- print(resources.getString("DISPLAY_MORE"));
- flush();
- int c = readCharacter();
- if (c == '\r' || c == '\n') {
- // one step forward
- showLines = 1;
- }
- else if (c != 'q') {
- // page forward
- showLines = height - 1;
- }
-
- tputs("carriage_return");
- if (c == 'q') {
- // cancel
- break;
- }
- }
- }
-
- // NOTE: toString() is important here due to AnsiString being retarded
- buff.append(item.toString());
- int strippedItemLength = wcwidth(Ansi.stripAnsi(item.toString()), 0);
- for (int i = 0; i < (maxWidth - strippedItemLength); i++) {
- buff.append(' ');
- }
- realLength += maxWidth;
- }
-
- if (buff.length() > 0) {
- rawPrintln(buff.toString());
- }
- }
-
- //
- // Non-supported Terminal Support
- //
-
- private Thread maskThread;
-
- private void beforeReadLine(final String prompt, final Character mask) {
- if (mask != null && maskThread == null) {
- final String fullPrompt = "\r" + prompt
- + " "
- + " "
- + " "
- + "\r" + prompt;
-
- maskThread = new Thread()
- {
- public void run() {
- while (!interrupted()) {
- try {
- Writer out = getOutput();
- out.write(fullPrompt);
- out.flush();
- sleep(3);
- }
- catch (IOException e) {
- return;
- }
- catch (InterruptedException e) {
- return;
- }
- }
- }
- };
-
- maskThread.setPriority(Thread.MAX_PRIORITY);
- maskThread.setDaemon(true);
- maskThread.start();
- }
- }
-
- private void afterReadLine() {
- if (maskThread != null && maskThread.isAlive()) {
- maskThread.interrupt();
- }
-
- maskThread = null;
- }
-
- /**
- * Erases the current line with the existing prompt, then redraws the line
- * with the provided prompt and buffer
- * @param prompt
- * the new prompt
- * @param buffer
- * the buffer to be drawn
- * @param cursorDest
- * where you want the cursor set when the line has been drawn.
- * -1 for end of line.
- * */
- public void resetPromptLine(String prompt, String buffer, int cursorDest) throws IOException {
- // move cursor to end of line
- moveToEnd();
-
- // backspace all text, including prompt
- buf.buffer.append(this.prompt);
- int promptLength = 0;
- if (this.prompt != null) {
- promptLength = this.prompt.length();
- }
-
- buf.cursor += promptLength;
- setPrompt("");
- backspaceAll();
-
- setPrompt(prompt);
- redrawLine();
- setBuffer(buffer);
-
- // move cursor to destination (-1 will move to end of line)
- if (cursorDest < 0) cursorDest = buffer.length();
- setCursorPosition(cursorDest);
-
- flush();
- }
-
- public void printSearchStatus(String searchTerm, String match) throws IOException {
- printSearchStatus(searchTerm, match, "(reverse-i-search)`");
- }
-
- public void printForwardSearchStatus(String searchTerm, String match) throws IOException {
- printSearchStatus(searchTerm, match, "(i-search)`");
- }
-
- private void printSearchStatus(String searchTerm, String match, String searchLabel) throws IOException {
- String prompt = searchLabel + searchTerm + "': ";
- int cursorDest = match.indexOf(searchTerm);
- resetPromptLine(prompt, match, cursorDest);
- }
-
- public void restoreLine(String originalPrompt, int cursorDest) throws IOException {
- // TODO move cursor to matched string
- String prompt = lastLine(originalPrompt);
- String buffer = buf.buffer.toString();
- resetPromptLine(prompt, buffer, cursorDest);
- }
-
- //
- // History search
- //
- /**
- * Search backward in history from a given position.
- *
- * @param searchTerm substring to search for.
- * @param startIndex the index from which on to search
- * @return index where this substring has been found, or -1 else.
- */
- public int searchBackwards(String searchTerm, int startIndex) {
- return searchBackwards(searchTerm, startIndex, false);
- }
-
- /**
- * Search backwards in history from the current position.
- *
- * @param searchTerm substring to search for.
- * @return index where the substring has been found, or -1 else.
- */
- public int searchBackwards(String searchTerm) {
- return searchBackwards(searchTerm, history.index());
- }
-
-
- public int searchBackwards(String searchTerm, int startIndex, boolean startsWith) {
- ListIterator it = history.entries(startIndex);
- while (it.hasPrevious()) {
- History.Entry e = it.previous();
- if (startsWith) {
- if (e.value().toString().startsWith(searchTerm)) {
- return e.index();
- }
- } else {
- if (e.value().toString().contains(searchTerm)) {
- return e.index();
- }
- }
- }
- return -1;
- }
-
- /**
- * Search forward in history from a given position.
- *
- * @param searchTerm substring to search for.
- * @param startIndex the index from which on to search
- * @return index where this substring has been found, or -1 else.
- */
- public int searchForwards(String searchTerm, int startIndex) {
- return searchForwards(searchTerm, startIndex, false);
- }
- /**
- * Search forwards in history from the current position.
- *
- * @param searchTerm substring to search for.
- * @return index where the substring has been found, or -1 else.
- */
- public int searchForwards(String searchTerm) {
- return searchForwards(searchTerm, history.index());
- }
-
- public int searchForwards(String searchTerm, int startIndex, boolean startsWith) {
- if (startIndex >= history.size()) {
- startIndex = history.size() - 1;
- }
-
- ListIterator it = history.entries(startIndex);
-
- if (searchIndex != -1 && it.hasNext()) {
- it.next();
- }
-
- while (it.hasNext()) {
- History.Entry e = it.next();
- if (startsWith) {
- if (e.value().toString().startsWith(searchTerm)) {
- return e.index();
- }
- } else {
- if (e.value().toString().contains(searchTerm)) {
- return e.index();
- }
- }
- }
- return -1;
- }
-
- //
- // Helpers
- //
-
- /**
- * Checks to see if the specified character is a delimiter. We consider a
- * character a delimiter if it is anything but a letter or digit.
- *
- * @param c The character to test
- * @return True if it is a delimiter
- */
- private static boolean isDelimiter(final char c) {
- return !Character.isLetterOrDigit(c);
- }
-
- /**
- * Checks to see if a character is a whitespace character. Currently
- * this delegates to {@link Character#isWhitespace(char)}, however
- * eventually it should be hooked up so that the definition of whitespace
- * can be configured, as readline does.
- *
- * @param c The character to check
- * @return true if the character is a whitespace
- */
- private static boolean isWhitespace(final char c) {
- return Character.isWhitespace (c);
- }
-
- private boolean tputs(String cap, Object... params) throws IOException {
- String str = terminal.getStringCapability(cap);
- if (str == null) {
- return false;
- }
- Curses.tputs(out, str, params);
- return true;
- }
-
-}
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.internal.le/share/classes/jdk/internal/jline/console/CursorBuffer.java
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/CursorBuffer.java Tue Dec 11 11:45:43 2018 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,121 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console;
-
-import static jdk.internal.jline.internal.Preconditions.checkNotNull;
-
-/**
- * A holder for a {@link StringBuilder} that also contains the current cursor position.
- *
- * @author Marc Prud'hommeaux
- * @author Jason Dillon
- * @since 2.0
- */
-public class CursorBuffer
-{
- private boolean overTyping = false;
-
- public int cursor = 0;
-
- public final StringBuilder buffer = new StringBuilder();
-
- public CursorBuffer copy () {
- CursorBuffer that = new CursorBuffer();
- that.overTyping = this.overTyping;
- that.cursor = this.cursor;
- that.buffer.append (this.toString());
-
- return that;
- }
-
- public boolean isOverTyping() {
- return overTyping;
- }
-
- public void setOverTyping(final boolean b) {
- overTyping = b;
- }
-
- public int length() {
- return buffer.length();
- }
-
- public char nextChar() {
- if (cursor == buffer.length()) {
- return 0;
- } else {
- return buffer.charAt(cursor);
- }
- }
-
- public char current() {
- if (cursor <= 0) {
- return 0;
- }
-
- return buffer.charAt(cursor - 1);
- }
-
- /**
- * Write the specific character into the buffer, setting the cursor position
- * ahead one. The text may overwrite or insert based on the current setting
- * of {@link #isOverTyping}.
- *
- * @param c the character to insert
- */
- public void write(final char c) {
- buffer.insert(cursor++, c);
- if (isOverTyping() && cursor < buffer.length()) {
- buffer.deleteCharAt(cursor);
- }
- }
-
- /**
- * Insert the specified chars into the buffer, setting the cursor to the end of the insertion point.
- */
- public void write(final CharSequence str) {
- checkNotNull(str);
-
- if (buffer.length() == 0) {
- buffer.append(str);
- }
- else {
- buffer.insert(cursor, str);
- }
-
- cursor += str.length();
-
- if (isOverTyping() && cursor < buffer.length()) {
- buffer.delete(cursor, cursor + str.length());
- }
- }
-
- public boolean clear() {
- if (buffer.length() == 0) {
- return false;
- }
-
- buffer.delete(0, buffer.length());
- cursor = 0;
- return true;
- }
-
- public String upToCursor() {
- if (cursor <= 0) {
- return "";
- }
-
- return buffer.substring(0, cursor);
- }
-
- @Override
- public String toString() {
- return buffer.toString();
- }
-}
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.internal.le/share/classes/jdk/internal/jline/console/KeyMap.java
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/KeyMap.java Tue Dec 11 11:45:43 2018 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,577 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * The KeyMap class contains all bindings from keys to operations.
- *
- * @author Guillaume Nodet
- * @since 2.6
- */
-public class KeyMap {
-
- public static final String VI_MOVE = "vi-move";
- public static final String VI_INSERT = "vi-insert";
- public static final String EMACS = "emacs";
- public static final String EMACS_STANDARD = "emacs-standard";
- public static final String EMACS_CTLX = "emacs-ctlx";
- public static final String EMACS_META = "emacs-meta";
-
- private static final int KEYMAP_LENGTH = 256;
-
- private static final Object NULL_FUNCTION = new Object();
-
- private Object[] mapping = new Object[KEYMAP_LENGTH];
- private Object anotherKey = null;
- private String name;
-
- public KeyMap(String name) {
- this(name, new Object[KEYMAP_LENGTH]);
- }
-
- @Deprecated
- public KeyMap(String name, boolean unused) {
- this(name);
- }
-
- protected KeyMap(String name, Object[] mapping) {
- this.mapping = mapping;
- this.name = name;
- }
-
- public String getName() {
- return name;
- }
-
- public Object getAnotherKey() {
- return anotherKey;
- }
-
- public void from(KeyMap other) {
- this.mapping = other.mapping;
- this.anotherKey = other.anotherKey;
- }
-
- public Object getBound( CharSequence keySeq ) {
- if (keySeq != null && keySeq.length() > 0) {
- KeyMap map = this;
- for (int i = 0; i < keySeq.length(); i++) {
- char c = keySeq.charAt(i);
- if (c > 255) {
- return Operation.SELF_INSERT;
- }
- if (map.mapping[c] instanceof KeyMap) {
- if (i == keySeq.length() - 1) {
- return map.mapping[c];
- } else {
- map = (KeyMap) map.mapping[c];
- }
- } else {
- return map.mapping[c];
- }
- }
- }
- return null;
- }
-
- public void bindIfNotBound( CharSequence keySeq, Object function ) {
-
- bind (this, keySeq, function, true);
- }
-
- public void bind( CharSequence keySeq, Object function ) {
-
- bind (this, keySeq, function, false);
- }
-
- private static void bind( KeyMap map, CharSequence keySeq, Object function ) {
-
- bind (map, keySeq, function, false);
- }
-
- private static void bind( KeyMap map, CharSequence keySeq, Object function,
- boolean onlyIfNotBound ) {
-
- if (keySeq != null && keySeq.length() > 0) {
- for (int i = 0; i < keySeq.length(); i++) {
- char c = keySeq.charAt(i);
- if (c >= map.mapping.length) {
- return;
- }
- if (i < keySeq.length() - 1) {
- if (!(map.mapping[c] instanceof KeyMap)) {
- KeyMap m = new KeyMap("anonymous");
- if (map.mapping[c] != Operation.DO_LOWERCASE_VERSION) {
- m.anotherKey = map.mapping[c];
- }
- map.mapping[c] = m;
- }
- map = (KeyMap) map.mapping[c];
- } else {
- if (function == null) {
- function = NULL_FUNCTION;
- }
- if (map.mapping[c] instanceof KeyMap) {
- map.anotherKey = function;
- } else {
- Object op = map.mapping[c];
- if (onlyIfNotBound == false
- || op == null
- || op == Operation.DO_LOWERCASE_VERSION
- || op == Operation.VI_MOVEMENT_MODE ) {
-
- }
-
- map.mapping[c] = function;
- }
- }
- }
- }
- }
-
- public void setBlinkMatchingParen(boolean on) {
- if (on) {
- bind( "}", Operation.INSERT_CLOSE_CURLY );
- bind( ")", Operation.INSERT_CLOSE_PAREN );
- bind( "]", Operation.INSERT_CLOSE_SQUARE );
- }
- }
-
- private static void bindArrowKeys(KeyMap map) {
-
- // MS-DOS
- bind( map, "\033[0A", Operation.PREVIOUS_HISTORY );
- bind( map, "\033[0B", Operation.BACKWARD_CHAR );
- bind( map, "\033[0C", Operation.FORWARD_CHAR );
- bind( map, "\033[0D", Operation.NEXT_HISTORY );
-
- // Windows
- bind( map, "\340\000", Operation.KILL_WHOLE_LINE );
- bind( map, "\340\107", Operation.BEGINNING_OF_LINE );
- bind( map, "\340\110", Operation.PREVIOUS_HISTORY );
- bind( map, "\340\111", Operation.BEGINNING_OF_HISTORY );
- bind( map, "\340\113", Operation.BACKWARD_CHAR );
- bind( map, "\340\115", Operation.FORWARD_CHAR );
- bind( map, "\340\117", Operation.END_OF_LINE );
- bind( map, "\340\120", Operation.NEXT_HISTORY );
- bind( map, "\340\121", Operation.END_OF_HISTORY );
- bind( map, "\340\122", Operation.OVERWRITE_MODE );
- bind( map, "\340\123", Operation.DELETE_CHAR );
-
- bind( map, "\000\107", Operation.BEGINNING_OF_LINE );
- bind( map, "\000\110", Operation.PREVIOUS_HISTORY );
- bind( map, "\000\111", Operation.BEGINNING_OF_HISTORY );
- bind( map, "\000\110", Operation.PREVIOUS_HISTORY );
- bind( map, "\000\113", Operation.BACKWARD_CHAR );
- bind( map, "\000\115", Operation.FORWARD_CHAR );
- bind( map, "\000\117", Operation.END_OF_LINE );
- bind( map, "\000\120", Operation.NEXT_HISTORY );
- bind( map, "\000\121", Operation.END_OF_HISTORY );
- bind( map, "\000\122", Operation.OVERWRITE_MODE );
- bind( map, "\000\123", Operation.DELETE_CHAR );
-
- bind( map, "\033[A", Operation.PREVIOUS_HISTORY );
- bind( map, "\033[B", Operation.NEXT_HISTORY );
- bind( map, "\033[C", Operation.FORWARD_CHAR );
- bind( map, "\033[D", Operation.BACKWARD_CHAR );
- bind( map, "\033[H", Operation.BEGINNING_OF_LINE );
- bind( map, "\033[F", Operation.END_OF_LINE );
-
- bind( map, "\033OA", Operation.PREVIOUS_HISTORY );
- bind( map, "\033OB", Operation.NEXT_HISTORY );
- bind( map, "\033OC", Operation.FORWARD_CHAR );
- bind( map, "\033OD", Operation.BACKWARD_CHAR );
- bind( map, "\033OH", Operation.BEGINNING_OF_LINE );
- bind( map, "\033OF", Operation.END_OF_LINE );
-
- bind( map, "\033[1~", Operation.BEGINNING_OF_LINE);
- bind( map, "\033[4~", Operation.END_OF_LINE);
- bind( map, "\033[3~", Operation.DELETE_CHAR);
-
- // MINGW32
- bind( map, "\0340H", Operation.PREVIOUS_HISTORY );
- bind( map, "\0340P", Operation.NEXT_HISTORY );
- bind( map, "\0340M", Operation.FORWARD_CHAR );
- bind( map, "\0340K", Operation.BACKWARD_CHAR );
- }
-
-// public boolean isConvertMetaCharsToAscii() {
-// return convertMetaCharsToAscii;
-// }
-
-// public void setConvertMetaCharsToAscii(boolean convertMetaCharsToAscii) {
-// this.convertMetaCharsToAscii = convertMetaCharsToAscii;
-// }
-
- public static boolean isMeta( char c ) {
- return c > 0x7f && c <= 0xff;
- }
-
- public static char unMeta( char c ) {
- return (char) (c & 0x7F);
- }
-
- public static char meta( char c ) {
- return (char) (c | 0x80);
- }
-
- public static Map keyMaps() {
- Map keyMaps = new HashMap();
-
- KeyMap emacs = emacs();
- bindArrowKeys(emacs);
- keyMaps.put(EMACS, emacs);
- keyMaps.put(EMACS_STANDARD, emacs);
- keyMaps.put(EMACS_CTLX, (KeyMap) emacs.getBound("\u0018"));
- keyMaps.put(EMACS_META, (KeyMap) emacs.getBound("\u001b"));
-
- KeyMap viMov = viMovement();
- bindArrowKeys(viMov);
- keyMaps.put(VI_MOVE, viMov);
- keyMaps.put("vi-command", viMov);
- keyMaps.put("vi", viMov);
-
- KeyMap viIns = viInsertion();
- bindArrowKeys(viIns);
- keyMaps.put(VI_INSERT, viIns);
-
- return keyMaps;
- }
-
- public static KeyMap emacs() {
- Object[] map = new Object[KEYMAP_LENGTH];
- Object[] ctrl = new Object[] {
- // Control keys.
- Operation.SET_MARK, /* Control-@ */
- Operation.BEGINNING_OF_LINE, /* Control-A */
- Operation.BACKWARD_CHAR, /* Control-B */
- Operation.INTERRUPT, /* Control-C */
- Operation.EXIT_OR_DELETE_CHAR, /* Control-D */
- Operation.END_OF_LINE, /* Control-E */
- Operation.FORWARD_CHAR, /* Control-F */
- Operation.ABORT, /* Control-G */
- Operation.BACKWARD_DELETE_CHAR, /* Control-H */
- Operation.COMPLETE, /* Control-I */
- Operation.ACCEPT_LINE, /* Control-J */
- Operation.KILL_LINE, /* Control-K */
- Operation.CLEAR_SCREEN, /* Control-L */
- Operation.ACCEPT_LINE, /* Control-M */
- Operation.NEXT_HISTORY, /* Control-N */
- null, /* Control-O */
- Operation.PREVIOUS_HISTORY, /* Control-P */
- Operation.QUOTED_INSERT, /* Control-Q */
- Operation.REVERSE_SEARCH_HISTORY, /* Control-R */
- Operation.FORWARD_SEARCH_HISTORY, /* Control-S */
- Operation.TRANSPOSE_CHARS, /* Control-T */
- Operation.UNIX_LINE_DISCARD, /* Control-U */
- Operation.QUOTED_INSERT, /* Control-V */
- Operation.UNIX_WORD_RUBOUT, /* Control-W */
- emacsCtrlX(), /* Control-X */
- Operation.YANK, /* Control-Y */
- null, /* Control-Z */
- emacsMeta(), /* Control-[ */
- null, /* Control-\ */
- Operation.CHARACTER_SEARCH, /* Control-] */
- null, /* Control-^ */
- Operation.UNDO, /* Control-_ */
- };
- System.arraycopy( ctrl, 0, map, 0, ctrl.length );
- for (int i = 32; i < 256; i++) {
- map[i] = Operation.SELF_INSERT;
- }
- map[DELETE] = Operation.BACKWARD_DELETE_CHAR;
- return new KeyMap(EMACS, map);
- }
-
- public static final char CTRL_D = (char) 4;
- public static final char CTRL_G = (char) 7;
- public static final char CTRL_H = (char) 8;
- public static final char CTRL_I = (char) 9;
- public static final char CTRL_J = (char) 10;
- public static final char CTRL_M = (char) 13;
- public static final char CTRL_R = (char) 18;
- public static final char CTRL_S = (char) 19;
- public static final char CTRL_U = (char) 21;
- public static final char CTRL_X = (char) 24;
- public static final char CTRL_Y = (char) 25;
- public static final char ESCAPE = (char) 27; /* Ctrl-[ */
- public static final char CTRL_OB = (char) 27; /* Ctrl-[ */
- public static final char CTRL_CB = (char) 29; /* Ctrl-] */
-
- public static final int DELETE = (char) 127;
-
- public static KeyMap emacsCtrlX() {
- Object[] map = new Object[KEYMAP_LENGTH];
- map[CTRL_G] = Operation.ABORT;
- map[CTRL_R] = Operation.RE_READ_INIT_FILE;
- map[CTRL_U] = Operation.UNDO;
- map[CTRL_X] = Operation.EXCHANGE_POINT_AND_MARK;
- map['('] = Operation.START_KBD_MACRO;
- map[')'] = Operation.END_KBD_MACRO;
- for (int i = 'A'; i <= 'Z'; i++) {
- map[i] = Operation.DO_LOWERCASE_VERSION;
- }
- map['e'] = Operation.CALL_LAST_KBD_MACRO;
- map[DELETE] = Operation.KILL_LINE;
- return new KeyMap(EMACS_CTLX, map);
- }
-
- public static KeyMap emacsMeta() {
- Object[] map = new Object[KEYMAP_LENGTH];
- map[CTRL_G] = Operation.ABORT;
- map[CTRL_H] = Operation.BACKWARD_KILL_WORD;
- map[CTRL_I] = Operation.TAB_INSERT;
- map[CTRL_J] = Operation.VI_EDITING_MODE;
- map[CTRL_M] = Operation.VI_EDITING_MODE;
- map[CTRL_R] = Operation.REVERT_LINE;
- map[CTRL_Y] = Operation.YANK_NTH_ARG;
- map[CTRL_OB] = Operation.COMPLETE;
- map[CTRL_CB] = Operation.CHARACTER_SEARCH_BACKWARD;
- map[' '] = Operation.SET_MARK;
- map['#'] = Operation.INSERT_COMMENT;
- map['&'] = Operation.TILDE_EXPAND;
- map['*'] = Operation.INSERT_COMPLETIONS;
- map['-'] = Operation.DIGIT_ARGUMENT;
- map['.'] = Operation.YANK_LAST_ARG;
- map['<'] = Operation.BEGINNING_OF_HISTORY;
- map['='] = Operation.POSSIBLE_COMPLETIONS;
- map['>'] = Operation.END_OF_HISTORY;
- map['?'] = Operation.POSSIBLE_COMPLETIONS;
- for (int i = 'A'; i <= 'Z'; i++) {
- map[i] = Operation.DO_LOWERCASE_VERSION;
- }
- map['\\'] = Operation.DELETE_HORIZONTAL_SPACE;
- map['_'] = Operation.YANK_LAST_ARG;
- map['b'] = Operation.BACKWARD_WORD;
- map['c'] = Operation.CAPITALIZE_WORD;
- map['d'] = Operation.KILL_WORD;
- map['f'] = Operation.FORWARD_WORD;
- map['l'] = Operation.DOWNCASE_WORD;
- map['p'] = Operation.NON_INCREMENTAL_REVERSE_SEARCH_HISTORY;
- map['r'] = Operation.REVERT_LINE;
- map['t'] = Operation.TRANSPOSE_WORDS;
- map['u'] = Operation.UPCASE_WORD;
- map['y'] = Operation.YANK_POP;
- map['~'] = Operation.TILDE_EXPAND;
- map[DELETE] = Operation.BACKWARD_KILL_WORD;
- return new KeyMap(EMACS_META, map);
- }
-
- public static KeyMap viInsertion() {
- Object[] map = new Object[KEYMAP_LENGTH];
- Object[] ctrl = new Object[] {
- // Control keys.
- null, /* Control-@ */
- Operation.SELF_INSERT, /* Control-A */
- Operation.SELF_INSERT, /* Control-B */
- Operation.SELF_INSERT, /* Control-C */
- Operation.VI_EOF_MAYBE, /* Control-D */
- Operation.SELF_INSERT, /* Control-E */
- Operation.SELF_INSERT, /* Control-F */
- Operation.SELF_INSERT, /* Control-G */
- Operation.BACKWARD_DELETE_CHAR, /* Control-H */
- Operation.COMPLETE, /* Control-I */
- Operation.ACCEPT_LINE, /* Control-J */
- Operation.SELF_INSERT, /* Control-K */
- Operation.SELF_INSERT, /* Control-L */
- Operation.ACCEPT_LINE, /* Control-M */
- Operation.MENU_COMPLETE, /* Control-N */
- Operation.SELF_INSERT, /* Control-O */
- Operation.MENU_COMPLETE_BACKWARD, /* Control-P */
- Operation.SELF_INSERT, /* Control-Q */
- Operation.REVERSE_SEARCH_HISTORY, /* Control-R */
- Operation.FORWARD_SEARCH_HISTORY, /* Control-S */
- Operation.TRANSPOSE_CHARS, /* Control-T */
- Operation.UNIX_LINE_DISCARD, /* Control-U */
- Operation.QUOTED_INSERT, /* Control-V */
- Operation.UNIX_WORD_RUBOUT, /* Control-W */
- Operation.SELF_INSERT, /* Control-X */
- Operation.YANK, /* Control-Y */
- Operation.SELF_INSERT, /* Control-Z */
- Operation.VI_MOVEMENT_MODE, /* Control-[ */
- Operation.SELF_INSERT, /* Control-\ */
- Operation.SELF_INSERT, /* Control-] */
- Operation.SELF_INSERT, /* Control-^ */
- Operation.UNDO, /* Control-_ */
- };
- System.arraycopy( ctrl, 0, map, 0, ctrl.length );
- for (int i = 32; i < 256; i++) {
- map[i] = Operation.SELF_INSERT;
- }
- map[DELETE] = Operation.BACKWARD_DELETE_CHAR;
- return new KeyMap(VI_INSERT, map);
- }
-
- public static KeyMap viMovement() {
- Object[] map = new Object[KEYMAP_LENGTH];
- Object[] low = new Object[] {
- // Control keys.
- null, /* Control-@ */
- null, /* Control-A */
- null, /* Control-B */
- Operation.INTERRUPT, /* Control-C */
- /*
- * ^D is supposed to move down half a screen. In bash
- * appears to be ignored.
- */
- Operation.VI_EOF_MAYBE, /* Control-D */
- Operation.EMACS_EDITING_MODE, /* Control-E */
- null, /* Control-F */
- Operation.ABORT, /* Control-G */
- Operation.BACKWARD_CHAR, /* Control-H */
- null, /* Control-I */
- Operation.VI_MOVE_ACCEPT_LINE, /* Control-J */
- Operation.KILL_LINE, /* Control-K */
- Operation.CLEAR_SCREEN, /* Control-L */
- Operation.VI_MOVE_ACCEPT_LINE, /* Control-M */
- Operation.VI_NEXT_HISTORY, /* Control-N */
- null, /* Control-O */
- Operation.VI_PREVIOUS_HISTORY, /* Control-P */
- /*
- * My testing with readline is the ^Q is ignored.
- * Maybe this should be null?
- */
- Operation.QUOTED_INSERT, /* Control-Q */
-
- /*
- * TODO - Very broken. While in forward/reverse
- * history search the VI keyset should go out the
- * window and we need to enter a very simple keymap.
- */
- Operation.REVERSE_SEARCH_HISTORY, /* Control-R */
- /* TODO */
- Operation.FORWARD_SEARCH_HISTORY, /* Control-S */
- Operation.TRANSPOSE_CHARS, /* Control-T */
- Operation.UNIX_LINE_DISCARD, /* Control-U */
- /* TODO */
- Operation.QUOTED_INSERT, /* Control-V */
- Operation.UNIX_WORD_RUBOUT, /* Control-W */
- null, /* Control-X */
- /* TODO */
- Operation.YANK, /* Control-Y */
- null, /* Control-Z */
- emacsMeta(), /* Control-[ */
- null, /* Control-\ */
- /* TODO */
- Operation.CHARACTER_SEARCH, /* Control-] */
- null, /* Control-^ */
- /* TODO */
- Operation.UNDO, /* Control-_ */
- Operation.FORWARD_CHAR, /* SPACE */
- null, /* ! */
- null, /* " */
- Operation.VI_INSERT_COMMENT, /* # */
- Operation.END_OF_LINE, /* $ */
- Operation.VI_MATCH, /* % */
- Operation.VI_TILDE_EXPAND, /* & */
- null, /* ' */
- null, /* ( */
- null, /* ) */
- /* TODO */
- Operation.VI_COMPLETE, /* * */
- Operation.VI_NEXT_HISTORY, /* + */
- Operation.VI_CHAR_SEARCH, /* , */
- Operation.VI_PREVIOUS_HISTORY, /* - */
- /* TODO */
- Operation.VI_REDO, /* . */
- Operation.VI_SEARCH, /* / */
- Operation.VI_BEGINNING_OF_LINE_OR_ARG_DIGIT, /* 0 */
- Operation.VI_ARG_DIGIT, /* 1 */
- Operation.VI_ARG_DIGIT, /* 2 */
- Operation.VI_ARG_DIGIT, /* 3 */
- Operation.VI_ARG_DIGIT, /* 4 */
- Operation.VI_ARG_DIGIT, /* 5 */
- Operation.VI_ARG_DIGIT, /* 6 */
- Operation.VI_ARG_DIGIT, /* 7 */
- Operation.VI_ARG_DIGIT, /* 8 */
- Operation.VI_ARG_DIGIT, /* 9 */
- null, /* : */
- Operation.VI_CHAR_SEARCH, /* ; */
- null, /* < */
- Operation.VI_COMPLETE, /* = */
- null, /* > */
- Operation.VI_SEARCH, /* ? */
- null, /* @ */
- Operation.VI_APPEND_EOL, /* A */
- Operation.VI_PREV_WORD, /* B */
- Operation.VI_CHANGE_TO_EOL, /* C */
- Operation.VI_DELETE_TO_EOL, /* D */
- Operation.VI_END_WORD, /* E */
- Operation.VI_CHAR_SEARCH, /* F */
- /* I need to read up on what this does */
- Operation.VI_FETCH_HISTORY, /* G */
- null, /* H */
- Operation.VI_INSERT_BEG, /* I */
- null, /* J */
- null, /* K */
- null, /* L */
- null, /* M */
- Operation.VI_SEARCH_AGAIN, /* N */
- null, /* O */
- Operation.VI_PUT, /* P */
- null, /* Q */
- /* TODO */
- Operation.VI_REPLACE, /* R */
- Operation.VI_KILL_WHOLE_LINE, /* S */
- Operation.VI_CHAR_SEARCH, /* T */
- /* TODO */
- Operation.REVERT_LINE, /* U */
- null, /* V */
- Operation.VI_NEXT_WORD, /* W */
- Operation.VI_RUBOUT, /* X */
- Operation.VI_YANK_TO, /* Y */
- null, /* Z */
- null, /* [ */
- Operation.VI_COMPLETE, /* \ */
- null, /* ] */
- Operation.VI_FIRST_PRINT, /* ^ */
- Operation.VI_YANK_ARG, /* _ */
- Operation.VI_GOTO_MARK, /* ` */
- Operation.VI_APPEND_MODE, /* a */
- Operation.VI_PREV_WORD, /* b */
- Operation.VI_CHANGE_TO, /* c */
- Operation.VI_DELETE_TO, /* d */
- Operation.VI_END_WORD, /* e */
- Operation.VI_CHAR_SEARCH, /* f */
- null, /* g */
- Operation.BACKWARD_CHAR, /* h */
- Operation.VI_INSERTION_MODE, /* i */
- Operation.NEXT_HISTORY, /* j */
- Operation.PREVIOUS_HISTORY, /* k */
- Operation.FORWARD_CHAR, /* l */
- Operation.VI_SET_MARK, /* m */
- Operation.VI_SEARCH_AGAIN, /* n */
- null, /* o */
- Operation.VI_PUT, /* p */
- null, /* q */
- Operation.VI_CHANGE_CHAR, /* r */
- Operation.VI_SUBST, /* s */
- Operation.VI_CHAR_SEARCH, /* t */
- Operation.UNDO, /* u */
- null, /* v */
- Operation.VI_NEXT_WORD, /* w */
- Operation.VI_DELETE, /* x */
- Operation.VI_YANK_TO, /* y */
- null, /* z */
- null, /* { */
- Operation.VI_COLUMN, /* | */
- null, /* } */
- Operation.VI_CHANGE_CASE, /* ~ */
- Operation.VI_DELETE /* DEL */
- };
- System.arraycopy( low, 0, map, 0, low.length );
- for (int i = 128; i < 256; i++) {
- map[i] = null;
- }
- return new KeyMap(VI_MOVE, map);
- }
-}
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.internal.le/share/classes/jdk/internal/jline/console/KillRing.java
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/KillRing.java Tue Dec 11 11:45:43 2018 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,164 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console;
-
-/**
- * The kill ring class keeps killed text in a fixed size ring. In this
- * class we also keep record of whether or not the last command was a
- * kill or a yank. Depending on this, the class may behave
- * different. For instance, two consecutive kill-word commands fill
- * the same slot such that the next yank will return the two
- * previously killed words instead that only the last one. Likewise
- * yank pop requires that the previous command was either a yank or a
- * yank-pop.
- */
-public final class KillRing {
-
- /**
- * Default size is 60, like in emacs.
- */
- private static final int DEFAULT_SIZE = 60;
-
- private final String[] slots;
- private int head = 0;
- private boolean lastKill = false;
- private boolean lastYank = false;
-
- /**
- * Creates a new kill ring of the given size.
- */
- public KillRing(int size) {
- slots = new String[size];
- }
-
- /**
- * Creates a new kill ring of the default size. See {@link #DEFAULT_SIZE}.
- */
- public KillRing() {
- this(DEFAULT_SIZE);
- }
-
- /**
- * Resets the last-yank state.
- */
- public void resetLastYank() {
- lastYank = false;
- }
-
- /**
- * Resets the last-kill state.
- */
- public void resetLastKill() {
- lastKill = false;
- }
-
- /**
- * Returns {@code true} if the last command was a yank.
- */
- public boolean lastYank() {
- return lastYank;
- }
-
- /**
- * Adds the string to the kill-ring. Also sets lastYank to false
- * and lastKill to true.
- */
- public void add(String str) {
- lastYank = false;
-
- if (lastKill) {
- if (slots[head] != null) {
- slots[head] += str;
- return;
- }
- }
-
- lastKill = true;
- next();
- slots[head] = str;
- }
-
- /**
- * Adds the string to the kill-ring product of killing
- * backwards. If the previous command was a kill text one then
- * adds the text at the beginning of the previous kill to avoid
- * that two consecutive backwards kills followed by a yank leaves
- * things reversed.
- */
- public void addBackwards(String str) {
- lastYank = false;
-
- if (lastKill) {
- if (slots[head] != null) {
- slots[head] = str + slots[head];
- return;
- }
- }
-
- lastKill = true;
- next();
- slots[head] = str;
- }
-
- /**
- * Yanks a previously killed text. Returns {@code null} if the
- * ring is empty.
- */
- public String yank() {
- lastKill = false;
- lastYank = true;
- return slots[head];
- }
-
- /**
- * Moves the pointer to the current slot back and returns the text
- * in that position. If the previous command was not yank returns
- * null.
- */
- public String yankPop() {
- lastKill = false;
- if (lastYank) {
- prev();
- return slots[head];
- }
- return null;
- }
-
- /**
- * Moves the pointer to the current slot forward. If the end of
- * the slots is reached then points back to the beginning.
- */
- private void next() {
- if (head == 0 && slots[0] == null) {
- return;
- }
- head++;
- if (head == slots.length) {
- head = 0;
- }
- }
-
- /**
- * Moves the pointer to the current slot backwards. If the
- * beginning of the slots is reached then traverses the slot
- * backwards until one with not null content is found.
- */
- private void prev() {
- head--;
- if (head == -1) {
- int x = slots.length - 1;
- for (; x >= 0; x--) {
- if (slots[x] != null) {
- break;
- }
- }
- head = x;
- }
- }
-}
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.internal.le/share/classes/jdk/internal/jline/console/Operation.java
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/Operation.java Tue Dec 11 11:45:43 2018 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,161 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console;
-
-/**
- * List of all operations.
- *
- * @author Guillaume Nodet
- * @since 2.6
- */
-public enum Operation {
-
- ABORT,
- ACCEPT_LINE,
- ARROW_KEY_PREFIX,
- BACKWARD_BYTE,
- BACKWARD_CHAR,
- BACKWARD_DELETE_CHAR,
- BACKWARD_KILL_LINE,
- BACKWARD_KILL_WORD,
- BACKWARD_WORD,
- BEGINNING_OF_HISTORY,
- BEGINNING_OF_LINE,
- CALL_LAST_KBD_MACRO,
- CAPITALIZE_WORD,
- CHARACTER_SEARCH,
- CHARACTER_SEARCH_BACKWARD,
- CLEAR_SCREEN,
- COMPLETE,
- COPY_BACKWARD_WORD,
- COPY_FORWARD_WORD,
- COPY_REGION_AS_KILL,
- DELETE_CHAR,
- DELETE_CHAR_OR_LIST,
- DELETE_HORIZONTAL_SPACE,
- DIGIT_ARGUMENT,
- DO_LOWERCASE_VERSION,
- DOWNCASE_WORD,
- DUMP_FUNCTIONS,
- DUMP_MACROS,
- DUMP_VARIABLES,
- EMACS_EDITING_MODE,
- END_KBD_MACRO,
- END_OF_HISTORY,
- END_OF_LINE,
- EXCHANGE_POINT_AND_MARK,
- EXIT_OR_DELETE_CHAR,
- FORWARD_BACKWARD_DELETE_CHAR,
- FORWARD_BYTE,
- FORWARD_CHAR,
- FORWARD_SEARCH_HISTORY,
- FORWARD_WORD,
- HISTORY_SEARCH_BACKWARD,
- HISTORY_SEARCH_FORWARD,
- INSERT_CLOSE_CURLY,
- INSERT_CLOSE_PAREN,
- INSERT_CLOSE_SQUARE,
- INSERT_COMMENT,
- INSERT_COMPLETIONS,
- INTERRUPT,
- KILL_WHOLE_LINE,
- KILL_LINE,
- KILL_REGION,
- KILL_WORD,
- MENU_COMPLETE,
- MENU_COMPLETE_BACKWARD,
- NEXT_HISTORY,
- NON_INCREMENTAL_FORWARD_SEARCH_HISTORY,
- NON_INCREMENTAL_REVERSE_SEARCH_HISTORY,
- NON_INCREMENTAL_FORWARD_SEARCH_HISTORY_AGAIN,
- NON_INCREMENTAL_REVERSE_SEARCH_HISTORY_AGAIN,
- OLD_MENU_COMPLETE,
- OVERWRITE_MODE,
- PASTE_FROM_CLIPBOARD,
- POSSIBLE_COMPLETIONS,
- PREVIOUS_HISTORY,
- QUOTED_INSERT,
- QUIT,
- RE_READ_INIT_FILE,
- REDRAW_CURRENT_LINE,
- REVERSE_SEARCH_HISTORY,
- REVERT_LINE,
- SELF_INSERT,
- SET_MARK,
- SKIP_CSI_SEQUENCE,
- START_KBD_MACRO,
- TAB_INSERT,
- TILDE_EXPAND,
- TRANSPOSE_CHARS,
- TRANSPOSE_WORDS,
- TTY_STATUS,
- UNDO,
- UNIVERSAL_ARGUMENT,
- UNIX_FILENAME_RUBOUT,
- UNIX_LINE_DISCARD,
- UNIX_WORD_RUBOUT,
- UPCASE_WORD,
- YANK,
- YANK_LAST_ARG,
- YANK_NTH_ARG,
- YANK_POP,
- VI_APPEND_EOL,
- VI_APPEND_MODE,
- VI_ARG_DIGIT,
- VI_BACK_TO_INDENT,
- VI_BACKWARD_BIGWORD,
- VI_BACKWARD_WORD,
- VI_BWORD,
- VI_CHANGE_CASE,
- VI_CHANGE_CHAR,
- VI_CHANGE_TO,
- VI_CHANGE_TO_EOL,
- VI_CHAR_SEARCH,
- VI_COLUMN,
- VI_COMPLETE,
- VI_DELETE,
- VI_DELETE_TO,
- VI_DELETE_TO_EOL,
- VI_EDITING_MODE,
- VI_END_BIGWORD,
- VI_END_WORD,
- VI_EOF_MAYBE,
- VI_EWORD,
- VI_FWORD,
- VI_FETCH_HISTORY,
- VI_FIRST_PRINT,
- VI_FORWARD_BIGWORD,
- VI_FORWARD_WORD,
- VI_GOTO_MARK,
- VI_INSERT_BEG,
- VI_INSERTION_MODE,
- VI_KILL_WHOLE_LINE,
- VI_MATCH,
- VI_MOVEMENT_MODE,
- VI_NEXT_WORD,
- VI_OVERSTRIKE,
- VI_OVERSTRIKE_DELETE,
- VI_PREV_WORD,
- VI_PUT,
- VI_REDO,
- VI_REPLACE,
- VI_RUBOUT,
- VI_SEARCH,
- VI_SEARCH_AGAIN,
- VI_SET_MARK,
- VI_SUBST,
- VI_TILDE_EXPAND,
- VI_YANK_ARG,
- VI_YANK_TO,
- VI_MOVE_ACCEPT_LINE,
- VI_NEXT_HISTORY,
- VI_PREVIOUS_HISTORY,
- VI_INSERT_COMMENT,
- VI_BEGINNING_OF_LINE_OR_ARG_DIGIT,
-}
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.internal.le/share/classes/jdk/internal/jline/console/UserInterruptException.java
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/UserInterruptException.java Tue Dec 11 11:45:43 2018 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console;
-
-/**
- * This exception is thrown by {@link ConsoleReader#readLine} when
- * user interrupt handling is enabled and the user types the
- * interrupt character (ctrl-C). The partially entered line is
- * available via the {@link #getPartialLine()} method.
- */
-public class UserInterruptException
- extends RuntimeException
-{
- private static final long serialVersionUID = 6172232572140736750L;
-
- private final String partialLine;
-
- public UserInterruptException(String partialLine)
- {
- this.partialLine = partialLine;
- }
-
- /**
- * @return the partially entered line when ctrl-C was pressed
- */
- public String getPartialLine()
- {
- return partialLine;
- }
-}
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.internal.le/share/classes/jdk/internal/jline/console/WCWidth.java
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/WCWidth.java Tue Dec 11 11:45:43 2018 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,158 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console;
-
-public class WCWidth {
-
- /* The following two functions define the column width of an ISO 10646
- * character as follows:
- *
- * - The null character (U+0000) has a column width of 0.
- *
- * - Other C0/C1 control characters and DEL will lead to a return
- * value of -1.
- *
- * - Non-spacing and enclosing combining characters (general
- * category code Mn or Me in the Unicode database) have a
- * column width of 0.
- *
- * - SOFT HYPHEN (U+00AD) has a column width of 1.
- *
- * - Other format characters (general category code Cf in the Unicode
- * database) and ZERO WIDTH SPACE (U+200B) have a column width of 0.
- *
- * - Hangul Jamo medial vowels and final consonants (U+1160-U+11FF)
- * have a column width of 0.
- *
- * - Spacing characters in the East Asian Wide (W) or East Asian
- * Full-width (F) category as defined in Unicode Technical
- * Report #11 have a column width of 2.
- *
- * - All remaining characters (including all printable
- * ISO 8859-1 and WGL4 characters, Unicode control characters,
- * etc.) have a column width of 1.
- *
- * This implementation assumes that wchar_t characters are encoded
- * in ISO 10646.
- */
- public static int wcwidth(int ucs)
- {
-
- /* test for 8-bit control characters */
- if (ucs == 0)
- return 0;
- if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0))
- return -1;
-
- /* binary search in table of non-spacing characters */
- if (bisearch(ucs, combining, combining.length - 1))
- return 0;
-
- /* if we arrive here, ucs is not a combining or C0/C1 control character */
- return 1 +
- ((ucs >= 0x1100 &&
- (ucs <= 0x115f || /* Hangul Jamo init. consonants */
- ucs == 0x2329 || ucs == 0x232a ||
- (ucs >= 0x2e80 && ucs <= 0xa4cf &&
- ucs != 0x303f) || /* CJK ... Yi */
- (ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */
- (ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */
- (ucs >= 0xfe10 && ucs <= 0xfe19) || /* Vertical forms */
- (ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */
- (ucs >= 0xff00 && ucs <= 0xff60) || /* Fullwidth Forms */
- (ucs >= 0xffe0 && ucs <= 0xffe6) ||
- (ucs >= 0x20000 && ucs <= 0x2fffd) ||
- (ucs >= 0x30000 && ucs <= 0x3fffd))) ? 1 : 0);
- }
-
- /* sorted list of non-overlapping intervals of non-spacing characters */
- /* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */
- static Interval[] combining = {
- new Interval( 0x0300, 0x036F ), new Interval( 0x0483, 0x0486 ), new Interval( 0x0488, 0x0489 ),
- new Interval( 0x0591, 0x05BD ), new Interval( 0x05BF, 0x05BF ), new Interval( 0x05C1, 0x05C2 ),
- new Interval( 0x05C4, 0x05C5 ), new Interval( 0x05C7, 0x05C7 ), new Interval( 0x0600, 0x0603 ),
- new Interval( 0x0610, 0x0615 ), new Interval( 0x064B, 0x065E ), new Interval( 0x0670, 0x0670 ),
- new Interval( 0x06D6, 0x06E4 ), new Interval( 0x06E7, 0x06E8 ), new Interval( 0x06EA, 0x06ED ),
- new Interval( 0x070F, 0x070F ), new Interval( 0x0711, 0x0711 ), new Interval( 0x0730, 0x074A ),
- new Interval( 0x07A6, 0x07B0 ), new Interval( 0x07EB, 0x07F3 ), new Interval( 0x0901, 0x0902 ),
- new Interval( 0x093C, 0x093C ), new Interval( 0x0941, 0x0948 ), new Interval( 0x094D, 0x094D ),
- new Interval( 0x0951, 0x0954 ), new Interval( 0x0962, 0x0963 ), new Interval( 0x0981, 0x0981 ),
- new Interval( 0x09BC, 0x09BC ), new Interval( 0x09C1, 0x09C4 ), new Interval( 0x09CD, 0x09CD ),
- new Interval( 0x09E2, 0x09E3 ), new Interval( 0x0A01, 0x0A02 ), new Interval( 0x0A3C, 0x0A3C ),
- new Interval( 0x0A41, 0x0A42 ), new Interval( 0x0A47, 0x0A48 ), new Interval( 0x0A4B, 0x0A4D ),
- new Interval( 0x0A70, 0x0A71 ), new Interval( 0x0A81, 0x0A82 ), new Interval( 0x0ABC, 0x0ABC ),
- new Interval( 0x0AC1, 0x0AC5 ), new Interval( 0x0AC7, 0x0AC8 ), new Interval( 0x0ACD, 0x0ACD ),
- new Interval( 0x0AE2, 0x0AE3 ), new Interval( 0x0B01, 0x0B01 ), new Interval( 0x0B3C, 0x0B3C ),
- new Interval( 0x0B3F, 0x0B3F ), new Interval( 0x0B41, 0x0B43 ), new Interval( 0x0B4D, 0x0B4D ),
- new Interval( 0x0B56, 0x0B56 ), new Interval( 0x0B82, 0x0B82 ), new Interval( 0x0BC0, 0x0BC0 ),
- new Interval( 0x0BCD, 0x0BCD ), new Interval( 0x0C3E, 0x0C40 ), new Interval( 0x0C46, 0x0C48 ),
- new Interval( 0x0C4A, 0x0C4D ), new Interval( 0x0C55, 0x0C56 ), new Interval( 0x0CBC, 0x0CBC ),
- new Interval( 0x0CBF, 0x0CBF ), new Interval( 0x0CC6, 0x0CC6 ), new Interval( 0x0CCC, 0x0CCD ),
- new Interval( 0x0CE2, 0x0CE3 ), new Interval( 0x0D41, 0x0D43 ), new Interval( 0x0D4D, 0x0D4D ),
- new Interval( 0x0DCA, 0x0DCA ), new Interval( 0x0DD2, 0x0DD4 ), new Interval( 0x0DD6, 0x0DD6 ),
- new Interval( 0x0E31, 0x0E31 ), new Interval( 0x0E34, 0x0E3A ), new Interval( 0x0E47, 0x0E4E ),
- new Interval( 0x0EB1, 0x0EB1 ), new Interval( 0x0EB4, 0x0EB9 ), new Interval( 0x0EBB, 0x0EBC ),
- new Interval( 0x0EC8, 0x0ECD ), new Interval( 0x0F18, 0x0F19 ), new Interval( 0x0F35, 0x0F35 ),
- new Interval( 0x0F37, 0x0F37 ), new Interval( 0x0F39, 0x0F39 ), new Interval( 0x0F71, 0x0F7E ),
- new Interval( 0x0F80, 0x0F84 ), new Interval( 0x0F86, 0x0F87 ), new Interval( 0x0F90, 0x0F97 ),
- new Interval( 0x0F99, 0x0FBC ), new Interval( 0x0FC6, 0x0FC6 ), new Interval( 0x102D, 0x1030 ),
- new Interval( 0x1032, 0x1032 ), new Interval( 0x1036, 0x1037 ), new Interval( 0x1039, 0x1039 ),
- new Interval( 0x1058, 0x1059 ), new Interval( 0x1160, 0x11FF ), new Interval( 0x135F, 0x135F ),
- new Interval( 0x1712, 0x1714 ), new Interval( 0x1732, 0x1734 ), new Interval( 0x1752, 0x1753 ),
- new Interval( 0x1772, 0x1773 ), new Interval( 0x17B4, 0x17B5 ), new Interval( 0x17B7, 0x17BD ),
- new Interval( 0x17C6, 0x17C6 ), new Interval( 0x17C9, 0x17D3 ), new Interval( 0x17DD, 0x17DD ),
- new Interval( 0x180B, 0x180D ), new Interval( 0x18A9, 0x18A9 ), new Interval( 0x1920, 0x1922 ),
- new Interval( 0x1927, 0x1928 ), new Interval( 0x1932, 0x1932 ), new Interval( 0x1939, 0x193B ),
- new Interval( 0x1A17, 0x1A18 ), new Interval( 0x1B00, 0x1B03 ), new Interval( 0x1B34, 0x1B34 ),
- new Interval( 0x1B36, 0x1B3A ), new Interval( 0x1B3C, 0x1B3C ), new Interval( 0x1B42, 0x1B42 ),
- new Interval( 0x1B6B, 0x1B73 ), new Interval( 0x1DC0, 0x1DCA ), new Interval( 0x1DFE, 0x1DFF ),
- new Interval( 0x200B, 0x200F ), new Interval( 0x202A, 0x202E ), new Interval( 0x2060, 0x2063 ),
- new Interval( 0x206A, 0x206F ), new Interval( 0x20D0, 0x20EF ), new Interval( 0x302A, 0x302F ),
- new Interval( 0x3099, 0x309A ), new Interval( 0xA806, 0xA806 ), new Interval( 0xA80B, 0xA80B ),
- new Interval( 0xA825, 0xA826 ), new Interval( 0xFB1E, 0xFB1E ), new Interval( 0xFE00, 0xFE0F ),
- new Interval( 0xFE20, 0xFE23 ), new Interval( 0xFEFF, 0xFEFF ), new Interval( 0xFFF9, 0xFFFB ),
- new Interval( 0x10A01, 0x10A03 ), new Interval( 0x10A05, 0x10A06 ), new Interval( 0x10A0C, 0x10A0F ),
- new Interval( 0x10A38, 0x10A3A ), new Interval( 0x10A3F, 0x10A3F ), new Interval( 0x1D167, 0x1D169 ),
- new Interval( 0x1D173, 0x1D182 ), new Interval( 0x1D185, 0x1D18B ), new Interval( 0x1D1AA, 0x1D1AD ),
- new Interval( 0x1D242, 0x1D244 ), new Interval( 0xE0001, 0xE0001 ), new Interval( 0xE0020, 0xE007F ),
- new Interval( 0xE0100, 0xE01EF )
- };
-
- private static class Interval {
- public final int first;
- public final int last;
-
- public Interval(int first, int last) {
- this.first = first;
- this.last = last;
- }
- }
-
- /* auxiliary function for binary search in interval table */
- private static boolean bisearch(int ucs, Interval[] table, int max) {
- int min = 0;
- int mid;
-
- if (ucs < table[0].first || ucs > table[max].last)
- return false;
- while (max >= min) {
- mid = (min + max) / 2;
- if (ucs > table[mid].last)
- min = mid + 1;
- else if (ucs < table[mid].first)
- max = mid - 1;
- else
- return true;
- }
-
- return false;
- }
-
-
-}
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/AggregateCompleter.java
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/AggregateCompleter.java Tue Dec 11 11:45:43 2018 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console.completer;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.List;
-
-import static jdk.internal.jline.internal.Preconditions.checkNotNull;
-
-/**
- * Completer which contains multiple completers and aggregates them together.
- *
- * @author Jason Dillon
- * @since 2.3
- */
-public class AggregateCompleter
- implements Completer
-{
- private final List completers = new ArrayList();
-
- public AggregateCompleter() {
- // empty
- }
-
- /**
- * Construct an AggregateCompleter with the given collection of completers.
- * The completers will be used in the iteration order of the collection.
- *
- * @param completers the collection of completers
- */
- public AggregateCompleter(final Collection completers) {
- checkNotNull(completers);
- this.completers.addAll(completers);
- }
-
- /**
- * Construct an AggregateCompleter with the given completers.
- * The completers will be used in the order given.
- *
- * @param completers the completers
- */
- public AggregateCompleter(final Completer... completers) {
- this(Arrays.asList(completers));
- }
-
- /**
- * Retrieve the collection of completers currently being aggregated.
- *
- * @return the aggregated completers
- */
- public Collection getCompleters() {
- return completers;
- }
-
- /**
- * Perform a completion operation across all aggregated completers.
- *
- * @see Completer#complete(String, int, java.util.List)
- * @return the highest completion return value from all completers
- */
- public int complete(final String buffer, final int cursor, final List candidates) {
- // buffer could be null
- checkNotNull(candidates);
-
- List completions = new ArrayList(completers.size());
-
- // Run each completer, saving its completion results
- int max = -1;
- for (Completer completer : completers) {
- Completion completion = new Completion(candidates);
- completion.complete(completer, buffer, cursor);
-
- // Compute the max cursor position
- max = Math.max(max, completion.cursor);
-
- completions.add(completion);
- }
-
- // Append candidates from completions which have the same cursor position as max
- for (Completion completion : completions) {
- if (completion.cursor == max) {
- candidates.addAll(completion.candidates);
- }
- }
-
- return max;
- }
-
- /**
- * @return a string representing the aggregated completers
- */
- @Override
- public String toString() {
- return getClass().getSimpleName() + "{" +
- "completers=" + completers +
- '}';
- }
-
- private class Completion
- {
- public final List candidates;
-
- public int cursor;
-
- public Completion(final List candidates) {
- checkNotNull(candidates);
- this.candidates = new LinkedList(candidates);
- }
-
- public void complete(final Completer completer, final String buffer, final int cursor) {
- checkNotNull(completer);
- this.cursor = completer.complete(buffer, cursor, candidates);
- }
- }
-}
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/AnsiStringsCompleter.java
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/AnsiStringsCompleter.java Tue Dec 11 11:45:43 2018 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console.completer;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.SortedMap;
-import java.util.TreeMap;
-
-import jdk.internal.jline.internal.Ansi;
-
-import static jdk.internal.jline.internal.Preconditions.checkNotNull;
-
-/**
- * Completer for a set of strings.
- *
- * @author Jason Dillon
- * @since 2.3
- */
-public class AnsiStringsCompleter
- implements Completer
-{
- private final SortedMap strings = new TreeMap();
-
- public AnsiStringsCompleter() {
- // empty
- }
-
- public AnsiStringsCompleter(final Collection strings) {
- checkNotNull(strings);
- for (String str : strings) {
- this.strings.put(Ansi.stripAnsi(str), str);
- }
- }
-
- public AnsiStringsCompleter(final String... strings) {
- this(Arrays.asList(strings));
- }
-
- public Collection getStrings() {
- return strings.values();
- }
-
- public int complete(String buffer, final int cursor, final List candidates) {
- // buffer could be null
- checkNotNull(candidates);
-
- if (buffer == null) {
- candidates.addAll(strings.values());
- }
- else {
- buffer = Ansi.stripAnsi(buffer);
- for (Map.Entry match : strings.tailMap(buffer).entrySet()) {
- if (!match.getKey().startsWith(buffer)) {
- break;
- }
-
- candidates.add(match.getValue());
- }
- }
-
- return candidates.isEmpty() ? -1 : 0;
- }
-}
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/ArgumentCompleter.java
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/ArgumentCompleter.java Tue Dec 11 11:45:43 2018 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,457 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console.completer;
-
-import jdk.internal.jline.internal.Log;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.List;
-
-import static jdk.internal.jline.internal.Preconditions.checkNotNull;
-
-/**
- * A {@link Completer} implementation that invokes a child completer using the appropriate separator argument.
- * This can be used instead of the individual completers having to know about argument parsing semantics.
- *
- * @author Marc Prud'hommeaux
- * @author Jason Dillon
- * @since 2.3
- */
-public class ArgumentCompleter
- implements Completer
-{
- private final ArgumentDelimiter delimiter;
-
- private final List completers = new ArrayList();
-
- private boolean strict = true;
-
- /**
- * Create a new completer with the specified argument delimiter.
- *
- * @param delimiter The delimiter for parsing arguments
- * @param completers The embedded completers
- */
- public ArgumentCompleter(final ArgumentDelimiter delimiter, final Collection completers) {
- this.delimiter = checkNotNull(delimiter);
- checkNotNull(completers);
- this.completers.addAll(completers);
- }
-
- /**
- * Create a new completer with the specified argument delimiter.
- *
- * @param delimiter The delimiter for parsing arguments
- * @param completers The embedded completers
- */
- public ArgumentCompleter(final ArgumentDelimiter delimiter, final Completer... completers) {
- this(delimiter, Arrays.asList(completers));
- }
-
- /**
- * Create a new completer with the default {@link WhitespaceArgumentDelimiter}.
- *
- * @param completers The embedded completers
- */
- public ArgumentCompleter(final Completer... completers) {
- this(new WhitespaceArgumentDelimiter(), completers);
- }
-
- /**
- * Create a new completer with the default {@link WhitespaceArgumentDelimiter}.
- *
- * @param completers The embedded completers
- */
- public ArgumentCompleter(final List completers) {
- this(new WhitespaceArgumentDelimiter(), completers);
- }
-
- /**
- * If true, a completion at argument index N will only succeed
- * if all the completions from 0-(N-1) also succeed.
- */
- public void setStrict(final boolean strict) {
- this.strict = strict;
- }
-
- /**
- * Returns whether a completion at argument index N will success
- * if all the completions from arguments 0-(N-1) also succeed.
- *
- * @return True if strict.
- * @since 2.3
- */
- public boolean isStrict() {
- return this.strict;
- }
-
- /**
- * @since 2.3
- */
- public ArgumentDelimiter getDelimiter() {
- return delimiter;
- }
-
- /**
- * @since 2.3
- */
- public List getCompleters() {
- return completers;
- }
-
- public int complete(final String buffer, final int cursor, final List candidates) {
- // buffer can be null
- checkNotNull(candidates);
-
- ArgumentDelimiter delim = getDelimiter();
- ArgumentList list = delim.delimit(buffer, cursor);
- int argpos = list.getArgumentPosition();
- int argIndex = list.getCursorArgumentIndex();
-
- if (argIndex < 0) {
- return -1;
- }
-
- List completers = getCompleters();
- Completer completer;
-
- // if we are beyond the end of the completers, just use the last one
- if (argIndex >= completers.size()) {
- completer = completers.get(completers.size() - 1);
- }
- else {
- completer = completers.get(argIndex);
- }
-
- // ensure that all the previous completers are successful before allowing this completer to pass (only if strict).
- for (int i = 0; isStrict() && (i < argIndex); i++) {
- Completer sub = completers.get(i >= completers.size() ? (completers.size() - 1) : i);
- String[] args = list.getArguments();
- String arg = (args == null || i >= args.length) ? "" : args[i];
-
- List subCandidates = new LinkedList();
-
- if (sub.complete(arg, arg.length(), subCandidates) == -1) {
- return -1;
- }
-
- if (!subCandidates.contains(arg)) {
- return -1;
- }
- }
-
- int ret = completer.complete(list.getCursorArgument(), argpos, candidates);
-
- if (ret == -1) {
- return -1;
- }
-
- int pos = ret + list.getBufferPosition() - argpos;
-
- // Special case: when completing in the middle of a line, and the area under the cursor is a delimiter,
- // then trim any delimiters from the candidates, since we do not need to have an extra delimiter.
- //
- // E.g., if we have a completion for "foo", and we enter "f bar" into the buffer, and move to after the "f"
- // and hit TAB, we want "foo bar" instead of "foo bar".
-
- if ((cursor != buffer.length()) && delim.isDelimiter(buffer, cursor)) {
- for (int i = 0; i < candidates.size(); i++) {
- CharSequence val = candidates.get(i);
-
- while (val.length() > 0 && delim.isDelimiter(val, val.length() - 1)) {
- val = val.subSequence(0, val.length() - 1);
- }
-
- candidates.set(i, val);
- }
- }
-
- Log.trace("Completing ", buffer, " (pos=", cursor, ") with: ", candidates, ": offset=", pos);
-
- return pos;
- }
-
- /**
- * The {@link ArgumentCompleter.ArgumentDelimiter} allows custom breaking up of a {@link String} into individual
- * arguments in order to dispatch the arguments to the nested {@link Completer}.
- *
- * @author Marc Prud'hommeaux
- */
- public static interface ArgumentDelimiter
- {
- /**
- * Break the specified buffer into individual tokens that can be completed on their own.
- *
- * @param buffer The buffer to split
- * @param pos The current position of the cursor in the buffer
- * @return The tokens
- */
- ArgumentList delimit(CharSequence buffer, int pos);
-
- /**
- * Returns true if the specified character is a whitespace parameter.
- *
- * @param buffer The complete command buffer
- * @param pos The index of the character in the buffer
- * @return True if the character should be a delimiter
- */
- boolean isDelimiter(CharSequence buffer, int pos);
- }
-
- /**
- * Abstract implementation of a delimiter that uses the {@link #isDelimiter} method to determine if a particular
- * character should be used as a delimiter.
- *
- * @author Marc Prud'hommeaux
- */
- public abstract static class AbstractArgumentDelimiter
- implements ArgumentDelimiter
- {
- private char[] quoteChars = {'\'', '"'};
-
- private char[] escapeChars = {'\\'};
-
- public void setQuoteChars(final char[] chars) {
- this.quoteChars = chars;
- }
-
- public char[] getQuoteChars() {
- return this.quoteChars;
- }
-
- public void setEscapeChars(final char[] chars) {
- this.escapeChars = chars;
- }
-
- public char[] getEscapeChars() {
- return this.escapeChars;
- }
-
- public ArgumentList delimit(final CharSequence buffer, final int cursor) {
- List args = new LinkedList();
- StringBuilder arg = new StringBuilder();
- int argpos = -1;
- int bindex = -1;
- int quoteStart = -1;
-
- for (int i = 0; (buffer != null) && (i < buffer.length()); i++) {
- // once we reach the cursor, set the
- // position of the selected index
- if (i == cursor) {
- bindex = args.size();
- // the position in the current argument is just the
- // length of the current argument
- argpos = arg.length();
- }
-
- if (quoteStart < 0 && isQuoteChar(buffer, i)) {
- // Start a quote block
- quoteStart = i;
- } else if (quoteStart >= 0) {
- // In a quote block
- if (buffer.charAt(quoteStart) == buffer.charAt(i) && !isEscaped(buffer, i)) {
- // End the block; arg could be empty, but that's fine
- args.add(arg.toString());
- arg.setLength(0);
- quoteStart = -1;
- } else if (!isEscapeChar(buffer, i)) {
- // Take the next character
- arg.append(buffer.charAt(i));
- }
- } else {
- // Not in a quote block
- if (isDelimiter(buffer, i)) {
- if (arg.length() > 0) {
- args.add(arg.toString());
- arg.setLength(0); // reset the arg
- }
- } else if (!isEscapeChar(buffer, i)) {
- arg.append(buffer.charAt(i));
- }
- }
- }
-
- if (cursor == buffer.length()) {
- bindex = args.size();
- // the position in the current argument is just the
- // length of the current argument
- argpos = arg.length();
- }
- if (arg.length() > 0) {
- args.add(arg.toString());
- }
-
- return new ArgumentList(args.toArray(new String[args.size()]), bindex, argpos, cursor);
- }
-
- /**
- * Returns true if the specified character is a whitespace parameter. Check to ensure that the character is not
- * escaped by any of {@link #getQuoteChars}, and is not escaped by ant of the {@link #getEscapeChars}, and
- * returns true from {@link #isDelimiterChar}.
- *
- * @param buffer The complete command buffer
- * @param pos The index of the character in the buffer
- * @return True if the character should be a delimiter
- */
- public boolean isDelimiter(final CharSequence buffer, final int pos) {
- return !isQuoted(buffer, pos) && !isEscaped(buffer, pos) && isDelimiterChar(buffer, pos);
- }
-
- public boolean isQuoted(final CharSequence buffer, final int pos) {
- return false;
- }
-
- public boolean isQuoteChar(final CharSequence buffer, final int pos) {
- if (pos < 0) {
- return false;
- }
-
- for (int i = 0; (quoteChars != null) && (i < quoteChars.length); i++) {
- if (buffer.charAt(pos) == quoteChars[i]) {
- return !isEscaped(buffer, pos);
- }
- }
-
- return false;
- }
-
- /**
- * Check if this character is a valid escape char (i.e. one that has not been escaped)
- */
- public boolean isEscapeChar(final CharSequence buffer, final int pos) {
- if (pos < 0) {
- return false;
- }
-
- for (int i = 0; (escapeChars != null) && (i < escapeChars.length); i++) {
- if (buffer.charAt(pos) == escapeChars[i]) {
- return !isEscaped(buffer, pos); // escape escape
- }
- }
-
- return false;
- }
-
- /**
- * Check if a character is escaped (i.e. if the previous character is an escape)
- *
- * @param buffer
- * the buffer to check in
- * @param pos
- * the position of the character to check
- * @return true if the character at the specified position in the given buffer is an escape character and the character immediately preceding it is not an
- * escape character.
- */
- public boolean isEscaped(final CharSequence buffer, final int pos) {
- if (pos <= 0) {
- return false;
- }
-
- return isEscapeChar(buffer, pos - 1);
- }
-
- /**
- * Returns true if the character at the specified position if a delimiter. This method will only be called if
- * the character is not enclosed in any of the {@link #getQuoteChars}, and is not escaped by ant of the
- * {@link #getEscapeChars}. To perform escaping manually, override {@link #isDelimiter} instead.
- */
- public abstract boolean isDelimiterChar(CharSequence buffer, int pos);
- }
-
- /**
- * {@link ArgumentCompleter.ArgumentDelimiter} implementation that counts all whitespace (as reported by
- * {@link Character#isWhitespace}) as being a delimiter.
- *
- * @author Marc Prud'hommeaux
- */
- public static class WhitespaceArgumentDelimiter
- extends AbstractArgumentDelimiter
- {
- /**
- * The character is a delimiter if it is whitespace, and the
- * preceding character is not an escape character.
- */
- @Override
- public boolean isDelimiterChar(final CharSequence buffer, final int pos) {
- return Character.isWhitespace(buffer.charAt(pos));
- }
- }
-
- /**
- * The result of a delimited buffer.
- *
- * @author Marc Prud'hommeaux
- */
- public static class ArgumentList
- {
- private String[] arguments;
-
- private int cursorArgumentIndex;
-
- private int argumentPosition;
-
- private int bufferPosition;
-
- /**
- * @param arguments The array of tokens
- * @param cursorArgumentIndex The token index of the cursor
- * @param argumentPosition The position of the cursor in the current token
- * @param bufferPosition The position of the cursor in the whole buffer
- */
- public ArgumentList(final String[] arguments, final int cursorArgumentIndex, final int argumentPosition, final int bufferPosition) {
- this.arguments = checkNotNull(arguments);
- this.cursorArgumentIndex = cursorArgumentIndex;
- this.argumentPosition = argumentPosition;
- this.bufferPosition = bufferPosition;
- }
-
- public void setCursorArgumentIndex(final int i) {
- this.cursorArgumentIndex = i;
- }
-
- public int getCursorArgumentIndex() {
- return this.cursorArgumentIndex;
- }
-
- public String getCursorArgument() {
- if ((cursorArgumentIndex < 0) || (cursorArgumentIndex >= arguments.length)) {
- return null;
- }
-
- return arguments[cursorArgumentIndex];
- }
-
- public void setArgumentPosition(final int pos) {
- this.argumentPosition = pos;
- }
-
- public int getArgumentPosition() {
- return this.argumentPosition;
- }
-
- public void setArguments(final String[] arguments) {
- this.arguments = arguments;
- }
-
- public String[] getArguments() {
- return this.arguments;
- }
-
- public void setBufferPosition(final int pos) {
- this.bufferPosition = pos;
- }
-
- public int getBufferPosition() {
- return this.bufferPosition;
- }
- }
-}
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/CandidateListCompletionHandler.java
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/CandidateListCompletionHandler.java Tue Dec 11 11:45:43 2018 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,236 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console.completer;
-
-import jdk.internal.jline.console.ConsoleReader;
-import jdk.internal.jline.console.CursorBuffer;
-import jdk.internal.jline.internal.Ansi;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.ResourceBundle;
-import java.util.Set;
-
-/**
- * A {@link CompletionHandler} that deals with multiple distinct completions
- * by outputting the complete list of possibilities to the console. This
- * mimics the behavior of the
- * readline library.
- *
- * @author Marc Prud'hommeaux
- * @author Jason Dillon
- * @since 2.3
- */
-public class CandidateListCompletionHandler
- implements CompletionHandler
-{
- private boolean printSpaceAfterFullCompletion = true;
- private boolean stripAnsi;
-
- public boolean getPrintSpaceAfterFullCompletion() {
- return printSpaceAfterFullCompletion;
- }
-
- public void setPrintSpaceAfterFullCompletion(boolean printSpaceAfterFullCompletion) {
- this.printSpaceAfterFullCompletion = printSpaceAfterFullCompletion;
- }
-
- public boolean isStripAnsi() {
- return stripAnsi;
- }
-
- public void setStripAnsi(boolean stripAnsi) {
- this.stripAnsi = stripAnsi;
- }
-
- // TODO: handle quotes and escaped quotes && enable automatic escaping of whitespace
-
- public boolean complete(final ConsoleReader reader, final List candidates, final int pos) throws
- IOException
- {
- CursorBuffer buf = reader.getCursorBuffer();
-
- // if there is only one completion, then fill in the buffer
- if (candidates.size() == 1) {
- String value = Ansi.stripAnsi(candidates.get(0).toString());
-
- if (buf.cursor == buf.buffer.length()
- && printSpaceAfterFullCompletion
- && !value.endsWith(" ")) {
- value += " ";
- }
-
- // fail if the only candidate is the same as the current buffer
- if (value.equals(buf.toString())) {
- return false;
- }
-
- setBuffer(reader, value, pos);
-
- return true;
- }
- else if (candidates.size() > 1) {
- String value = getUnambiguousCompletions(candidates);
- setBuffer(reader, value, pos);
- }
-
- printCandidates(reader, candidates);
-
- // redraw the current console buffer
- reader.drawLine();
-
- return true;
- }
-
- public static void setBuffer(final ConsoleReader reader, final CharSequence value, final int offset) throws
- IOException
- {
- while ((reader.getCursorBuffer().cursor > offset) && reader.backspace()) {
- // empty
- }
-
- reader.putString(value);
- reader.setCursorPosition(offset + value.length());
- }
-
- /**
- * Print out the candidates. If the size of the candidates is greater than the
- * {@link ConsoleReader#getAutoprintThreshold}, they prompt with a warning.
- *
- * @param candidates the list of candidates to print
- */
- public static void printCandidates(final ConsoleReader reader, Collection candidates) throws
- IOException
- {
- Set distinct = new HashSet(candidates);
-
- if (distinct.size() > reader.getAutoprintThreshold()) {
- //noinspection StringConcatenation
- reader.println();
- reader.print(Messages.DISPLAY_CANDIDATES.format(distinct.size()));
- reader.flush();
-
- int c;
-
- String noOpt = Messages.DISPLAY_CANDIDATES_NO.format();
- String yesOpt = Messages.DISPLAY_CANDIDATES_YES.format();
- char[] allowed = {yesOpt.charAt(0), noOpt.charAt(0)};
-
- while ((c = reader.readCharacter(allowed)) != -1) {
- String tmp = new String(new char[]{(char) c});
-
- if (noOpt.startsWith(tmp)) {
- reader.println();
- return;
- }
- else if (yesOpt.startsWith(tmp)) {
- break;
- }
- else {
- reader.beep();
- }
- }
- }
-
- // copy the values and make them distinct, without otherwise affecting the ordering. Only do it if the sizes differ.
- if (distinct.size() != candidates.size()) {
- Collection copy = new ArrayList();
-
- for (CharSequence next : candidates) {
- if (!copy.contains(next)) {
- copy.add(next);
- }
- }
-
- candidates = copy;
- }
-
- reader.println();
- reader.printColumns(candidates);
- }
-
- /**
- * Returns a root that matches all the {@link String} elements of the specified {@link List},
- * or null if there are no commonalities. For example, if the list contains
- * foobar, foobaz, foobuz, the method will return foob.
- */
- private String getUnambiguousCompletions(final List candidates) {
- if (candidates == null || candidates.isEmpty()) {
- return null;
- }
-
- if (candidates.size() == 1) {
- return candidates.get(0).toString();
- }
-
- // convert to an array for speed
- String first = null;
- String[] strings = new String[candidates.size() - 1];
- for (int i = 0; i < candidates.size(); i++) {
- String str = candidates.get(i).toString();
- if (stripAnsi) {
- str = Ansi.stripAnsi(str);
- }
- if (first == null) {
- first = str;
- } else {
- strings[i - 1] = str;
- }
- }
-
- StringBuilder candidate = new StringBuilder();
-
- for (int i = 0; i < first.length(); i++) {
- if (startsWith(first.substring(0, i + 1), strings)) {
- candidate.append(first.charAt(i));
- }
- else {
- break;
- }
- }
-
- return candidate.toString();
- }
-
- /**
- * @return true is all the elements of candidates start with starts
- */
- private static boolean startsWith(final String starts, final String[] candidates) {
- for (String candidate : candidates) {
- if (!candidate.toLowerCase().startsWith(starts.toLowerCase())) {
- return false;
- }
- }
-
- return true;
- }
-
- private static enum Messages
- {
- DISPLAY_CANDIDATES,
- DISPLAY_CANDIDATES_YES,
- DISPLAY_CANDIDATES_NO,;
-
- private static final
- ResourceBundle
- bundle =
- ResourceBundle.getBundle(CandidateListCompletionHandler.class.getName(), Locale.getDefault());
-
- public String format(final Object... args) {
- if (bundle == null)
- return "";
- else
- return String.format(bundle.getString(name()), args);
- }
- }
-}
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/CandidateListCompletionHandler.properties
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/CandidateListCompletionHandler.properties Tue Dec 11 11:45:43 2018 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-#
-# Copyright (c) 2002-2016, the original author or authors.
-#
-# This software is distributable under the BSD license. See the terms of the
-# BSD license in the documentation provided with this software.
-#
-# http://www.opensource.org/licenses/bsd-license.php
-#
-
-DISPLAY_CANDIDATES=Display all %d possibilities? (y or n)
-DISPLAY_CANDIDATES_YES=y
-DISPLAY_CANDIDATES_NO=n
-DISPLAY_MORE=--More--
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/Completer.java
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/Completer.java Tue Dec 11 11:45:43 2018 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console.completer;
-
-import java.util.List;
-
-/**
- * A completer is the mechanism by which tab-completion candidates will be resolved.
- *
- * @author Marc Prud'hommeaux
- * @author Jason Dillon
- * @since 2.3
- */
-public interface Completer
-{
- //
- // FIXME: Check if we can use CharSequece for buffer?
- //
-
- /**
- * Populates candidates with a list of possible completions for the buffer.
- *
- * The candidates list will not be sorted before being displayed to the user: thus, the
- * complete method should sort the {@link List} before returning.
- *
- * @param buffer The buffer
- * @param cursor The current position of the cursor in the buffer
- * @param candidates The {@link List} of candidates to populate
- * @return The index of the buffer for which the completion will be relative
- */
- int complete(String buffer, int cursor, List candidates);
-}
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/CompletionHandler.java
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/CompletionHandler.java Tue Dec 11 11:45:43 2018 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console.completer;
-
-import jdk.internal.jline.console.ConsoleReader;
-
-import java.io.IOException;
-import java.util.List;
-
-/**
- * Handler for dealing with candidates for tab-completion.
- *
- * @author Marc Prud'hommeaux
- * @author Jason Dillon
- * @since 2.3
- */
-public interface CompletionHandler
-{
- boolean complete(ConsoleReader reader, List candidates, int position) throws IOException;
-}
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/EnumCompleter.java
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/EnumCompleter.java Tue Dec 11 11:45:43 2018 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console.completer;
-
-import static jdk.internal.jline.internal.Preconditions.checkNotNull;
-
-/**
- * {@link Completer} for {@link Enum} names.
- *
- * @author Jason Dillon
- * @since 2.3
- */
-public class EnumCompleter
- extends StringsCompleter
-{
- public EnumCompleter(Class extends Enum>> source) {
- this(source, true);
- }
-
- public EnumCompleter(Class extends Enum>> source, boolean toLowerCase) {
- checkNotNull(source);
-
- for (Enum> n : source.getEnumConstants()) {
- this.getStrings().add(toLowerCase ? n.name().toLowerCase() : n.name());
- }
- }
-}
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/FileNameCompleter.java
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/FileNameCompleter.java Tue Dec 11 11:45:43 2018 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,133 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console.completer;
-
-import jdk.internal.jline.internal.Configuration;
-
-import java.io.File;
-import java.util.List;
-
-import static jdk.internal.jline.internal.Preconditions.checkNotNull;
-
-/**
- * A file name completer takes the buffer and issues a list of
- * potential completions.
- *
- * This completer tries to behave as similar as possible to
- * bash's file name completion (using GNU readline)
- * with the following exceptions:
- *
- *
- * - Candidates that are directories will end with "/"
- * - Wildcard regular expressions are not evaluated or replaced
- * - The "~" character can be used to represent the user's home,
- * but it cannot complete to other users' homes, since java does
- * not provide any way of determining that easily
- *
- *
- * @author Marc Prud'hommeaux
- * @author Jason Dillon
- * @since 2.3
- */
-public class FileNameCompleter
- implements Completer
-{
- // TODO: Handle files with spaces in them
-
- private static final boolean OS_IS_WINDOWS;
-
- static {
- String os = Configuration.getOsName();
- OS_IS_WINDOWS = os.contains("windows");
- }
-
- public int complete(String buffer, final int cursor, final List candidates) {
- // buffer can be null
- checkNotNull(candidates);
-
- if (buffer == null) {
- buffer = "";
- }
-
- if (OS_IS_WINDOWS) {
- buffer = buffer.replace('/', '\\');
- }
-
- String translated = buffer;
-
- File homeDir = getUserHome();
-
- // Special character: ~ maps to the user's home directory
- if (translated.startsWith("~" + separator())) {
- translated = homeDir.getPath() + translated.substring(1);
- }
- else if (translated.startsWith("~")) {
- translated = homeDir.getParentFile().getAbsolutePath();
- }
- else if (!(new File(translated).isAbsolute())) {
- String cwd = getUserDir().getAbsolutePath();
- translated = cwd + separator() + translated;
- }
-
- File file = new File(translated);
- final File dir;
-
- if (translated.endsWith(separator())) {
- dir = file;
- }
- else {
- dir = file.getParentFile();
- }
-
- File[] entries = dir == null ? new File[0] : dir.listFiles();
-
- return matchFiles(buffer, translated, entries, candidates);
- }
-
- protected String separator() {
- return File.separator;
- }
-
- protected File getUserHome() {
- return Configuration.getUserHome();
- }
-
- protected File getUserDir() {
- return new File(".");
- }
-
- protected int matchFiles(final String buffer, final String translated, final File[] files, final List candidates) {
- if (files == null) {
- return -1;
- }
-
- int matches = 0;
-
- // first pass: just count the matches
- for (File file : files) {
- if (file.getAbsolutePath().startsWith(translated)) {
- matches++;
- }
- }
- for (File file : files) {
- if (file.getAbsolutePath().startsWith(translated)) {
- CharSequence name = file.getName() + (matches == 1 && file.isDirectory() ? separator() : " ");
- candidates.add(render(file, name).toString());
- }
- }
-
- final int index = buffer.lastIndexOf(separator());
-
- return index + separator().length();
- }
-
- protected CharSequence render(final File file, final CharSequence name) {
- return name;
- }
-}
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/NullCompleter.java
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/NullCompleter.java Tue Dec 11 11:45:43 2018 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console.completer;
-
-import java.util.List;
-
-/**
- * Null completer.
- *
- * @author Marc Prud'hommeaux
- * @author Jason Dillon
- * @since 2.3
- */
-public final class NullCompleter
- implements Completer
-{
- public static final NullCompleter INSTANCE = new NullCompleter();
-
- public int complete(final String buffer, final int cursor, final List candidates) {
- return -1;
- }
-}
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/StringsCompleter.java
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/StringsCompleter.java Tue Dec 11 11:45:43 2018 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console.completer;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.SortedSet;
-import java.util.TreeSet;
-
-import static jdk.internal.jline.internal.Preconditions.checkNotNull;
-
-/**
- * Completer for a set of strings.
- *
- * @author Jason Dillon
- * @since 2.3
- */
-public class StringsCompleter
- implements Completer
-{
- private final SortedSet strings = new TreeSet();
-
- public StringsCompleter() {
- // empty
- }
-
- public StringsCompleter(final Collection strings) {
- checkNotNull(strings);
- getStrings().addAll(strings);
- }
-
- public StringsCompleter(final String... strings) {
- this(Arrays.asList(strings));
- }
-
- public Collection getStrings() {
- return strings;
- }
-
- public int complete(final String buffer, final int cursor, final List candidates) {
- // buffer could be null
- checkNotNull(candidates);
-
- if (buffer == null) {
- candidates.addAll(strings);
- }
- else {
- for (String match : strings.tailSet(buffer)) {
- if (!match.startsWith(buffer)) {
- break;
- }
-
- candidates.add(match);
- }
- }
-
- return candidates.isEmpty() ? -1 : 0;
- }
-}
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/package-info.java
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/package-info.java Tue Dec 11 11:45:43 2018 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-/**
- * Console completer support.
- *
- * @since 2.3
- */
-package jdk.internal.jline.console.completer;
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.internal.le/share/classes/jdk/internal/jline/console/history/FileHistory.java
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/history/FileHistory.java Tue Dec 11 11:45:43 2018 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,135 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console.history;
-
-import java.io.BufferedOutputStream;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.Flushable;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.PrintStream;
-import java.io.Reader;
-
-import jdk.internal.jline.internal.Log;
-import static jdk.internal.jline.internal.Preconditions.checkNotNull;
-
-/**
- * {@link History} using a file for persistent backing.
- *
- * Implementers should install shutdown hook to call {@link FileHistory#flush}
- * to save history to disk.
- *
- * @author Jason Dillon
- * @since 2.0
- */
-public class FileHistory
- extends MemoryHistory
- implements PersistentHistory, Flushable
-{
- private final File file;
-
- /**
- * Load a history file into memory, truncating to default max size.
- */
- public FileHistory(final File file) throws IOException {
- this(file, true);
- }
-
- /**
- * Create a FileHistory, but only initialize if doInit is true. This allows
- * setting maxSize or other settings; call load() before using if doInit is
- * false.
- */
- public FileHistory(final File file, final boolean doInit) throws IOException {
- this.file = checkNotNull(file).getAbsoluteFile();
- if (doInit) {
- load();
- }
- }
-
- /**
- * Load history from file, e.g. if using delayed init.
- */
- public void load() throws IOException {
- load(file);
- }
-
- public File getFile() {
- return file;
- }
-
- public void load(final File file) throws IOException {
- checkNotNull(file);
- if (file.exists()) {
- Log.trace("Loading history from: ", file);
- FileReader reader = null;
- try{
- reader = new FileReader(file);
- load(reader);
- } finally{
- if(reader != null){
- reader.close();
- }
- }
- }
- }
-
- public void load(final InputStream input) throws IOException {
- checkNotNull(input);
- load(new InputStreamReader(input));
- }
-
- public void load(final Reader reader) throws IOException {
- checkNotNull(reader);
- BufferedReader input = new BufferedReader(reader);
-
- String item;
- while ((item = input.readLine()) != null) {
- internalAdd(item);
- }
- }
-
- public void flush() throws IOException {
- Log.trace("Flushing history");
-
- if (!file.exists()) {
- File dir = file.getParentFile();
- if (!dir.exists() && !dir.mkdirs()) {
- Log.warn("Failed to create directory: ", dir);
- }
- if (!file.createNewFile()) {
- Log.warn("Failed to create file: ", file);
- }
- }
-
- PrintStream out = new PrintStream(new BufferedOutputStream(new FileOutputStream(file)));
- try {
- for (Entry entry : this) {
- out.println(entry.value());
- }
- }
- finally {
- out.close();
- }
- }
-
- public void purge() throws IOException {
- Log.trace("Purging history");
-
- clear();
-
- if (!file.delete()) {
- Log.warn("Failed to delete history file: ", file);
- }
- }
-}
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.internal.le/share/classes/jdk/internal/jline/console/history/History.java
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/history/History.java Tue Dec 11 11:45:43 2018 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console.history;
-
-import java.util.Iterator;
-import java.util.ListIterator;
-
-/**
- * Console history.
- *
- * @author Marc Prud'hommeaux
- * @author Jason Dillon
- * @since 2.3
- */
-public interface History
- extends Iterable
-{
- int size();
-
- boolean isEmpty();
-
- int index();
-
- void clear();
-
- CharSequence get(int index);
-
- void add(CharSequence line);
-
- /**
- * Set the history item at the given index to the given CharSequence.
- *
- * @param index the index of the history offset
- * @param item the new item
- * @since 2.7
- */
- void set(int index, CharSequence item);
-
- /**
- * Remove the history element at the given index.
- *
- * @param i the index of the element to remove
- * @return the removed element
- * @since 2.7
- */
- CharSequence remove(int i);
-
- /**
- * Remove the first element from history.
- *
- * @return the removed element
- * @since 2.7
- */
- CharSequence removeFirst();
-
- /**
- * Remove the last element from history
- *
- * @return the removed element
- * @since 2.7
- */
- CharSequence removeLast();
-
- void replace(CharSequence item);
-
- //
- // Entries
- //
-
- interface Entry
- {
- int index();
-
- CharSequence value();
- }
-
- ListIterator entries(int index);
-
- ListIterator entries();
-
- Iterator iterator();
-
- //
- // Navigation
- //
-
- CharSequence current();
-
- boolean previous();
-
- boolean next();
-
- boolean moveToFirst();
-
- boolean moveToLast();
-
- boolean moveTo(int index);
-
- void moveToEnd();
-}
diff -r a659ccd1888d -r ddbd9744a3d5 src/jdk.internal.le/share/classes/jdk/internal/jline/console/history/MemoryHistory.java
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/history/MemoryHistory.java Tue Dec 11 11:45:43 2018 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,346 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console.history;
-
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.ListIterator;
-import java.util.NoSuchElementException;
-
-import static jdk.internal.jline.internal.Preconditions.checkNotNull;
-
-/**
- * Non-persistent {@link History}.
- *
- * @author Marc Prud'hommeaux
- * @author Jason Dillon
- * @since 2.3
- */
-public class MemoryHistory
- implements History
-{
- public static final int DEFAULT_MAX_SIZE = 500;
-
- private final LinkedList items = new LinkedList();
-
- private int maxSize = DEFAULT_MAX_SIZE;
-
- private boolean ignoreDuplicates = true;
-
- private boolean autoTrim = false;
-
- // NOTE: These are all ideas from looking at the Bash man page:
-
- // TODO: Add ignore space? (lines starting with a space are ignored)
-
- // TODO: Add ignore patterns?
-
- // TODO: Add history timestamp?
-
- // TODO: Add erase dups?
-
- private int offset = 0;
-
- private int index = 0;
-
- public void setMaxSize(final int maxSize) {
- this.maxSize = maxSize;
- maybeResize();
- }
-
- public int getMaxSize() {
- return maxSize;
- }
-
- public boolean isIgnoreDuplicates() {
- return ignoreDuplicates;
- }
-
- public void setIgnoreDuplicates(final boolean flag) {
- this.ignoreDuplicates = flag;
- }
-
- public boolean isAutoTrim() {
- return autoTrim;
- }
-
- public void setAutoTrim(final boolean flag) {
- this.autoTrim = flag;
- }
-
- public int size() {
- return items.size();
- }
-
- public boolean isEmpty() {
- return items.isEmpty();
- }
-
- public int index() {
- return offset + index;
- }
-
- public void clear() {
- items.clear();
- offset = 0;
- index = 0;
- }
-
- public CharSequence get(final int index) {
- return items.get(index - offset);
- }
-
- public void set(int index, CharSequence item) {
- items.set(index - offset, item);
- }
-
- public void add(CharSequence item) {
- checkNotNull(item);
-
- if (isAutoTrim()) {
- item = String.valueOf(item).trim();
- }
-
- if (isIgnoreDuplicates()) {
- if (!items.isEmpty() && item.equals(items.getLast())) {
- return;
- }
- }
-
- internalAdd(item);
- }
-
- public CharSequence remove(int i) {
- return items.remove(i);
- }
-
- public CharSequence removeFirst() {
- return items.removeFirst();
- }
-
- public CharSequence removeLast() {
- return items.removeLast();
- }
-
- protected void internalAdd(CharSequence item) {
- items.add(item);
-
- maybeResize();
- }
-
- public void replace(final CharSequence item) {
- items.removeLast();
- add(item);
- }
-
- private void maybeResize() {
- while (size() > getMaxSize()) {
- items.removeFirst();
- offset++;
- }
-
- index = size();
- }
-
- public ListIterator entries(final int index) {
- return new EntriesIterator(index - offset);
- }
-
- public ListIterator entries() {
- return entries(offset);
- }
-
- public Iterator