1/* 2 * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25package sun.jvm.hotspot.debugger; 26 27import java.io.*; 28 29/** InputLexer is the lexer through which the current set of debuggers 30 see the debug server. It provides the ability to read all of the 31 types the debuggers are interested in. All read operations are 32 blocking. */ 33 34public class InputLexer { 35 public InputLexer(BufferedInputStream in) throws IOException { 36 this.in = in; 37 pushedBack = false; 38 } 39 40 public void close() throws IOException { 41 in.close(); 42 } 43 44 /** Parses a boolean (really either a 0 or 1 integer in US-ASCII 45 encoding) on the input stream */ 46 public boolean parseBoolean() throws IOException { 47 int val = parseInt(); 48 return (val != 0); 49 } 50 51 /** Parses an int in US-ASCII encoding on the input stream */ 52 public int parseInt() throws IOException { 53 long l = parseLong(); 54 long mask = 0xFFFFFFFF00000000L; 55 if ((l & mask) != 0) { 56 throw new IOException("Overflow error reading int from debug server (read " + l + ")"); 57 } 58 return (int) l; 59 } 60 61 /** Parses a long in US-ASCII encoding on the input stream */ 62 public long parseLong() throws IOException { 63 skipWhitespace(); 64 byte b = readByte(); 65 if (!Character.isDigit((char) b)) { 66 error(); 67 } 68 long l = 0; 69 while (Character.isDigit((char) b)) { 70 l *= 10; 71 l += (b - '0'); 72 b = readByte(); 73 } 74 pushBack(b); 75 return l; 76 } 77 78 /** Parses an address in the form 0x12345678 in US-ASCII encoding on 79 the input stream */ 80 public long parseAddress() throws IOException { 81 skipWhitespace(); 82 byte b; 83 if ((b = readByte()) != '0') { 84 error(); 85 } 86 b = readByte(); 87 if (b != 'x') { 88 error(); 89 } 90 long val = 0; 91 while (isHexDigit((char) (b = readByte()))) { 92 val *= 16; 93 val += Character.digit((char) b, 16); 94 } 95 pushBack(b); 96 return val; 97 } 98 99 public void skipByte() throws IOException { 100 readByte(); 101 } 102 103 /** Reads binary data; one byte */ 104 public byte readByte() throws IOException { 105 if (pushedBack) { 106 pushedBack = false; 107 return backBuf; 108 } 109 return readByteInternal(); 110 } 111 112 /** Reads a block of binary data in BLOCKING fashion */ 113 public void readBytes(byte[] buf, int off, int len) throws IOException { 114 int startIdx = off; 115 int numRead = 0; 116 if (pushedBack) { 117 buf[startIdx] = backBuf; 118 pushedBack = false; 119 ++startIdx; 120 ++numRead; 121 } 122 while (numRead < len) { 123 numRead += in.read(buf, startIdx + numRead, len - numRead); 124 } 125 // if (numRead != len) { 126 // throw new IOException("Only read " + numRead + " out of " + 127 // len + " bytes requested"); 128 // } 129 } 130 131 /** Reads binary data; one 16-bit character in big-endian format */ 132 public char readChar() throws IOException { 133 int hi = ((int) readByte()) & 0xFF; 134 int lo = ((int) readByte()) & 0xFF; 135 return (char) ((hi << 8) | lo); 136 } 137 138 /** Reads binary data; one 32-bit unsigned int in big-endian format. 139 Returned as a long. */ 140 public long readUnsignedInt() throws IOException { 141 long b1 = ((long) readByte()) & 0xFF; 142 long b2 = ((long) readByte()) & 0xFF; 143 long b3 = ((long) readByte()) & 0xFF; 144 long b4 = ((long) readByte()) & 0xFF; 145 146 return ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4); 147 } 148 149 /** Reads binary data; a US-ASCII string of the specified length */ 150 public String readByteString(int len) throws IOException { 151 byte[] b = new byte[len]; 152 for (int i = 0; i < len; i++) { 153 b[i] = readByte(); 154 } 155 try { 156 return new String(b, "US-ASCII"); 157 } 158 catch (UnsupportedEncodingException e) { 159 throw new IOException(e.toString()); 160 } 161 } 162 163 /** Reads binary data; a Unicode string of the specified length */ 164 public String readCharString(int len) throws IOException { 165 char[] c = new char[len]; 166 for (int i = 0; i < len; i++) { 167 c[i] = readChar(); 168 } 169 return new String(c); 170 } 171 172 //---------------------------------------------------------------------- 173 // Internals only below this point 174 // 175 176 private void skipWhitespace() throws IOException { 177 byte b; 178 while (Character.isWhitespace((char) (b = readByte()))) { 179 } 180 pushBack(b); 181 } 182 183 private boolean isHexDigit(char c) { 184 return (('0' <= c && c <= '9') || 185 ('a' <= c && c <= 'f') || 186 ('A' <= c && c <= 'F')); 187 } 188 189 private void pushBack(byte b) { 190 if (pushedBack) { 191 throw new InternalError("Only one character pushback supported"); 192 } 193 backBuf = b; 194 pushedBack = true; 195 } 196 197 private byte readByteInternal() throws IOException { 198 int i = in.read(); 199 if (i == -1) { 200 throw new IOException("End-of-file reached while reading from server"); 201 } 202 return (byte) i; 203 } 204 205 private void error() throws IOException { 206 throw new IOException("Error parsing output of debug server"); 207 } 208 209 private BufferedInputStream in; 210 private boolean pushedBack; 211 private byte backBuf; 212} 213