001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package jcc;
028:
029: //import java.io.PrintStream;
030: // Miscellaneous support routines
031:
032: public class Util {
033: // How many bytes of storage for a particular signature?
034: static public int argsSize(String sig) {
035: int argsSize = 0;
036:
037: for (int pos = 0; sig.charAt(pos) != Const.SIGC_ENDMETHOD; pos++) {
038: switch (sig.charAt(pos)) {
039: case Const.SIGC_BOOLEAN:
040: case Const.SIGC_BYTE:
041: case Const.SIGC_CHAR:
042: case Const.SIGC_SHORT:
043: case Const.SIGC_INT:
044: case Const.SIGC_FLOAT:
045: argsSize++;
046: break;
047:
048: case Const.SIGC_LONG:
049: case Const.SIGC_DOUBLE:
050: argsSize += 2;
051: break;
052:
053: case Const.SIGC_CLASS:
054: argsSize++;
055: while (sig.charAt(pos) != Const.SIGC_ENDCLASS) {
056: pos++;
057: }
058: break;
059:
060: case Const.SIGC_ARRAY:
061: argsSize++;
062: while (sig.charAt(pos) == Const.SIGC_ARRAY) {
063: pos++;
064: }
065:
066: if (sig.charAt(pos) == Const.SIGC_CLASS) {
067: while (sig.charAt(pos) != Const.SIGC_ENDCLASS) {
068: pos++;
069: }
070: }
071: break;
072:
073: case Const.SIGC_METHOD:
074: break;
075:
076: default:
077: System.err.println("Error: unparseable signature: "
078: + sig);
079: System.exit(3);
080: }
081:
082: }
083:
084: return argsSize;
085: }
086:
087: static public String parseReturnType(String sig) {
088: int pos = 0, len = sig.length();
089:
090: for (; pos < len && sig.charAt(pos) != Const.SIGC_ENDMETHOD; pos++)
091: ;
092:
093: for (pos++; pos < len; pos++) {
094: switch (sig.charAt(pos)) {
095: case Const.SIGC_BOOLEAN:
096: return "jboolean";
097: case Const.SIGC_BYTE:
098: return "jbyte";
099: case Const.SIGC_CHAR:
100: return "jchar";
101: case Const.SIGC_SHORT:
102: return "jshort";
103: case Const.SIGC_INT:
104: return "jint";
105: case Const.SIGC_FLOAT:
106: return "jfloat";
107: case Const.SIGC_LONG:
108: return "jlong";
109: case Const.SIGC_DOUBLE:
110: return "jdouble";
111: case Const.SIGC_VOID:
112: return "void";
113: case Const.SIGC_CLASS:
114: case Const.SIGC_ARRAY:
115: return "jobject";
116: default:
117: System.err.println("Error: unparseable signature: "
118: + sig);
119: System.exit(3);
120: }
121: }
122: // to make javac happy
123: return null;
124: }
125:
126: // Replace characters C doesn't like with underscores
127: public static String convertToClassName(String name) {
128: char chars[] = name.toCharArray();
129:
130: for (int i = 0; i < chars.length; i++) {
131: switch (chars[i]) {
132: case '/':
133: case '.':
134: case '$':
135: chars[i] = '_';
136: }
137: }
138:
139: return String.valueOf(chars);
140: }
141:
142: public static String accessToString(int access) {
143: String result = "";
144: if ((access & Const.ACC_PUBLIC) != 0) {
145: result += "public ";
146: }
147: if ((access & Const.ACC_PRIVATE) != 0) {
148: result += "private ";
149: }
150: if ((access & Const.ACC_PROTECTED) != 0) {
151: result += "protected ";
152: }
153: if ((access & Const.ACC_STATIC) != 0) {
154: result += "static ";
155: }
156: if ((access & Const.ACC_TRANSIENT) != 0) {
157: result += "transient ";
158: }
159: if ((access & Const.ACC_SYNCHRONIZED) != 0) {
160: result += "synchronized ";
161: }
162: if ((access & Const.ACC_ABSTRACT) != 0) {
163: result += "abstract ";
164: }
165: if ((access & Const.ACC_NATIVE) != 0) {
166: result += "native ";
167: }
168: if ((access & Const.ACC_FINAL) != 0) {
169: result += "final ";
170: }
171: if ((access & Const.ACC_VOLATILE) != 0) {
172: result += "volatile ";
173: }
174: if ((access & Const.ACC_INTERFACE) != 0) {
175: result += "interface ";
176: }
177: return result;
178: }
179:
180: //
181: // given a full-Unicode Java String value, produce a byte array
182: // containing the UTF-8 encoding of it.
183: //
184: public static String unicodeToUTF(String in) {
185: int n = in.length();
186: StringBuffer t = new StringBuffer(3 * n); // conservative sizing.
187: int nt = 0;
188: for (int i = 0; i < n; i++) {
189: char c = in.charAt(i);
190: if (c == '\u0000') {
191: t.append('\u00c0');
192: t.append('\u0080');
193: nt += 2;
194: } else if (c <= '\u007f') {
195: t.append(c);
196: nt += 1;
197: } else if (c <= '\u07ff') {
198: t.append((char) ('\u00c0' | (c >> 6)));
199: t.append((char) ('\u0080' | (c & 0x3f)));
200: nt += 2;
201: } else {
202: t.append((char) ('\u00e0' | (c >> 12)));
203: t.append((char) ('\u0080' | ((c >> 6) & 0x3f)));
204: t.append((char) ('\u0080' | (c & 0x3f)));
205: nt += 3;
206: }
207: }
208: if (nt == n)
209: return in;
210: else
211: return t.toString();
212: }
213:
214: // Create a JNI external name from the given classname and methodname.
215: // If typename is not null, then we are producing a JNI name for an
216: // overloaded method, and we must include the type name, also.
217: public static String convertToJNIName(String classname,
218: String methodname, String typename) {
219: StringBuffer result = new StringBuffer("Java_");
220: stringToJNI(result, classname);
221: result.append('_');
222: stringToJNI(result, methodname);
223: if (typename != null) {
224: result.append("__");
225: // Only include the stuff inside the parentheses.
226: stringToJNI(result, typename.substring(1, typename
227: .indexOf(')')));
228: }
229: return result.toString();
230: }
231:
232: private static void stringToJNI(StringBuffer result, String name) {
233: int length = name.length();
234: for (int i = 0; i < length; i++) {
235: char ch = name.charAt(i);
236: if (ch <= 0x7f && Character.isLetterOrDigit(ch)) {
237: result.append(ch);
238: } else {
239: result.append('_');
240: switch (ch) {
241: case '/':
242: break; // the _ is all we need
243: case '_':
244: result.append('1');
245: break;
246: case ';':
247: result.append('2');
248: break;
249: case '[':
250: result.append('3');
251: break;
252: default: {
253: // Adding 0x100000 to a 16-bit number forces
254: // toHexString to produce a string of the form "10xxxx".
255: // Discard the initial "1" to get the right result.
256: String t = Integer.toHexString(ch + 0x100000);
257: result.append(t.substring(1));
258: }
259: }
260: }
261: }
262: }
263: }
|