package com.netscape.pkisilent.argparser; // --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program 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 for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- /** * Copyright John E. Lloyd, 2004. All rights reserved. Permission to use, copy, * modify and redistribute is granted, provided that this copyright notice is * retained and the author is given credit whenever appropriate. * * This software is distributed "as is", without any warranty, including any * implied warranty of merchantability or fitness for a particular use. The * author assumes no responsibility for, and shall not be liable for, any * special, indirect, or consequential damages, or any damages whatsoever, * arising out of or in connection with the use of this software. */ class StringScanner { private char[] buf; private int idx; private int len; private String stringDelimiters = ""; public StringScanner(String s) { buf = new char[s.length() + 1]; s.getChars(0, s.length(), buf, 0); len = s.length(); buf[len] = 0; idx = 0; } public int getIndex() { return idx; } public void setIndex(int i) { if (i < 0) { idx = 0; } else if (i > len) { idx = len; } else { idx = i; } } public void setStringDelimiters(String s) { stringDelimiters = s; } public String getStringDelimiters() { return stringDelimiters; } public char scanChar() throws StringScanException { int idxSave = idx; skipWhiteSpace(); try { if (buf[idx] == '\'') { return scanQuotedChar(); } else { return scanUnquotedChar(); } } catch (StringScanException e) { idx = idxSave; throw e; } } public char scanQuotedChar() throws StringScanException { StringScanException exception = null; char retval = 0; int idxSave = idx; skipWhiteSpace(); if (idx == len) { exception = new StringScanException(idx, "end of input"); } else if (buf[idx++] == '\'') { try { retval = scanUnquotedChar(); } catch (StringScanException e) { exception = e; } if (exception == null) { if (idx == len) { exception = new StringScanException(idx, "end of input"); } else if (buf[idx++] != '\'') { exception = new StringScanException(idx - 1, "unclosed quoted character"); } } } else { exception = new StringScanException(idx - 1, "uninitialized quoted character"); } if (exception != null) { idx = idxSave; throw exception; } return retval; } public char scanUnquotedChar() throws StringScanException { StringScanException exception = null; char c, retval = 0; int idxSave = idx; if (idx == len) { exception = new StringScanException(idx, "end of input"); } else if ((c = buf[idx++]) == '\\') { if (idx == len) { exception = new StringScanException(idx, "end of input"); } else { c = buf[idx++]; if (c == '"') { retval = '"'; } else if (c == '\'') { retval = '\''; } else if (c == '\\') { retval = '\\'; } else if (c == 'n') { retval = '\n'; } else if (c == 't') { retval = '\t'; } else if (c == 'b') { retval = '\b'; } else if (c == 'r') { retval = '\r'; } else if (c == 'f') { retval = '\f'; } else if ('0' <= c && c < '8') { int v = c - '0'; for (int j = 0; j < 2; j++) { if (idx == len) { break; } c = buf[idx]; if ('0' <= c && c < '8' && (v * 8 + (c - '0')) <= 255) { v = v * 8 + (c - '0'); idx++; } else { break; } } retval = (char) v; } else { exception = new StringScanException(idx - 1, "illegal escape character '" + c + "'"); } } } else { retval = c; } if (exception != null) { idx = idxSave; throw exception; } return retval; } public String scanQuotedString() throws StringScanException { StringScanException exception = null; StringBuffer sbuf = new StringBuffer(len); char c; int idxSave = idx; skipWhiteSpace(); if (idx == len) { exception = new StringScanException(idx, "end of input"); } else if ((c = buf[idx++]) == '"') { while (idx < len && (c = buf[idx]) != '"' && c != '\n') { if (c == '\\') { try { c = scanUnquotedChar(); } catch (StringScanException e) { exception = e; break; } } else { idx++; } sbuf.append(c); } if (exception == null && idx >= len) { exception = new StringScanException(len, "end of input"); } else if (exception == null && c == '\n') { exception = new StringScanException(idx, "unclosed quoted string"); } else { idx++; } } else { exception = new StringScanException(idx - 1, "quoted string must start with \""); } if (exception != null) { idx = idxSave; throw exception; } return sbuf.toString(); } public String scanNonWhiteSpaceString() throws StringScanException { StringBuffer sbuf = new StringBuffer(len); int idxSave = idx; char c; skipWhiteSpace(); if (idx == len) { StringScanException e = new StringScanException(idx, "end of input"); idx = idxSave; throw e; } else { c = buf[idx++]; while (idx < len && !Character.isWhitespace(c) && stringDelimiters.indexOf(c) == -1) { sbuf.append(c); c = buf[idx++]; } if (Character.isWhitespace(c) || stringDelimiters.indexOf(c) != -1) { idx--; } else { sbuf.append(c); } } return sbuf.toString(); } public String scanString() throws StringScanException { int idxSave = idx; skipWhiteSpace(); try { if (buf[idx] == '"') { return scanQuotedString(); } else { return scanNonWhiteSpaceString(); } } catch (StringScanException e) { idx = idxSave; throw e; } } public String getString() throws StringScanException { StringBuffer sbuf = new StringBuffer(len); while (idx < len) { sbuf.append(buf[idx++]); } return sbuf.toString(); } public long scanInt() throws StringScanException { int idxSave = idx; char c; int sign = 1; skipWhiteSpace(); if ((c = buf[idx]) == '-' || c == '+') { sign = (c == '-' ? -1 : 1); idx++; } try { if (idx == len) { throw new StringScanException(len, "end of input"); } else if ((c = buf[idx]) == '0') { if ((c = buf[idx + 1]) == 'x' || c == 'X') { idx += 2; return sign * scanInt(16, false); } else { return sign * scanInt(8, false); } } else { return sign * scanInt(10, false); } } catch (StringScanException e) { idx = idxSave; throw e; } } public long scanInt(int radix) throws StringScanException { return scanInt(radix, /* skipWhite= */true); } private String baseDesc(int radix) { switch (radix) { case 10: { return "decimal"; } case 8: { return "octal"; } case 16: { return "hex"; } default: { return "base " + radix; } } } public long scanInt(int radix, boolean skipWhite) throws StringScanException { StringScanException exception = null; int charval, idxSave = idx; char c; long val = 0; boolean negate = false; if (skipWhite) { skipWhiteSpace(); } if ((c = buf[idx]) == '-' || c == '+') { negate = (c == '-'); idx++; } if (idx >= len) { exception = new StringScanException(len, "end of input"); } else if ((charval = Character.digit(buf[idx++], radix)) == -1) { exception = new StringScanException(idx - 1, "malformed " + baseDesc(radix) + " integer"); } else { val = charval; while ((charval = Character.digit(buf[idx], radix)) != -1) { val = val * radix + charval; idx++; } if (Character.isLetter(c = buf[idx]) || Character.isDigit(c) || c == '_') { exception = new StringScanException(idx, "malformed " + baseDesc(radix) + " integer"); } } if (exception != null) { idx = idxSave; throw exception; } return negate ? -val : val; } public double scanDouble() throws StringScanException { StringScanException exception = null; int idxSave = idx; char c; // parse [-][0-9]*[.][0-9]*[eE][-][0-9]* boolean hasDigits = false; boolean signed; double value = 0; skipWhiteSpace(); if (idx == len) { exception = new StringScanException("end of input"); } else { if ((c = buf[idx]) == '-' || c == '+') { signed = true; idx++; } if (matchDigits()) { hasDigits = true; } if (buf[idx] == '.') { idx++; } if (!hasDigits && (buf[idx] < '0' || buf[idx] > '9')) { if (idx == len) { exception = new StringScanException(idx, "end of input"); } else { exception = new StringScanException(idx, "malformed floating number: no digits"); } } else { matchDigits(); if ((c = buf[idx]) == 'e' || c == 'E') { idx++; if ((c = buf[idx]) == '-' || c == '+') { signed = true; idx++; } if (buf[idx] < '0' || buf[idx] > '9') { if (idx == len) { exception = new StringScanException(idx, "end of input"); } else { exception = new StringScanException(idx, "malformed floating number: no digits in exponent"); } } else { matchDigits(); } } } } if (exception == null) { // if (Character.isLetterOrDigit(c=buf[idx]) || c == '_') // { exception = new StringScanException (idx, // "malformed floating number"); // } // else { try { value = Double.parseDouble(new String(buf, idxSave, idx - idxSave)); } catch (NumberFormatException e) { exception = new StringScanException(idx, "malformed floating number"); } } } if (exception != null) { idx = idxSave; throw exception; } return value; } public boolean scanBoolean() throws StringScanException { StringScanException exception = null; int idxSave = idx; String testStr = "false"; boolean testval = false; char c; skipWhiteSpace(); if (buf[idx] == 't') { testStr = "true"; testval = true; } else { testval = false; } int i = 0; for (i = 0; i < testStr.length(); i++) { if (testStr.charAt(i) != buf[idx]) { if (idx == len) { exception = new StringScanException(idx, "end of input"); } break; } idx++; } if (exception == null) { if (i < testStr.length() || Character.isLetterOrDigit(c = buf[idx]) || c == '_') { exception = new StringScanException(idx, "illegal boolean"); } } if (exception != null) { idx = idxSave; throw exception; } return testval; } public boolean matchString(String s) { int k = idx; for (int i = 0; i < s.length(); i++) { if (k >= len || s.charAt(i) != buf[k++]) { return false; } } idx = k; return true; } public boolean matchDigits() { int k = idx; char c; while ((c = buf[k]) >= '0' && c <= '9') { k++; } if (k > idx) { idx = k; return true; } else { return false; } } public void skipWhiteSpace() { while (Character.isWhitespace(buf[idx])) { idx++; } } private int skipWhiteSpace(int k) { while (Character.isWhitespace(buf[k])) { k++; } return k; } public boolean atEnd() { return idx == len; } public boolean atBeginning() { return idx == 0; } public void ungetc() { if (idx > 0) { idx--; } } public char getc() { char c = buf[idx]; if (idx < len) { idx++; } return c; } public char peekc() { return buf[idx]; } public String substring(int i0, int i1) { if (i0 < 0) { i0 = 0; } else if (i0 >= len) { i0 = len - 1; } if (i1 < 0) { i1 = 0; } else if (i1 > len) { i1 = len; } if (i1 <= i0) { return ""; } return new String(buf, i0, i1 - i0); } public String substring(int i0) { if (i0 < 0) { i0 = 0; } if (i0 >= len) { return ""; } else { return new String(buf, i0, len - i0); } } }