mirror of
https://github.com/2003scape/deep-c-rsc.git
synced 2024-03-22 05:49:51 -04:00
441 lines
16 KiB
Java
441 lines
16 KiB
Java
/*
|
|
* @(#) $(JCGO)/jtrsrc/com/ivmaisoft/jcgo/NameMapper.java --
|
|
* a part of JCGO translator.
|
|
**
|
|
* Project: JCGO (http://www.ivmaisoft.com/jcgo/)
|
|
* Copyright (C) 2001-2012 Ivan Maidanski <ivmai@mail.ru>
|
|
* All rights reserved.
|
|
*/
|
|
|
|
/*
|
|
* This 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; either version 2, or (at your option)
|
|
* any later version.
|
|
**
|
|
* This software 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 (GPL) for more details.
|
|
**
|
|
* Linking this library statically or dynamically with other modules is
|
|
* making a combined work based on this library. Thus, the terms and
|
|
* conditions of the GNU General Public License cover the whole
|
|
* combination.
|
|
**
|
|
* As a special exception, the copyright holders of this library give you
|
|
* permission to link this library with independent modules to produce an
|
|
* executable, regardless of the license terms of these independent
|
|
* modules, and to copy and distribute the resulting executable under
|
|
* terms of your choice, provided that you also meet, for each linked
|
|
* independent module, the terms and conditions of the license of that
|
|
* module. An independent module is a module which is not derived from
|
|
* or based on this library. If you modify this library, you may extend
|
|
* this exception to your version of the library, but you are not
|
|
* obligated to do so. If you do not wish to do so, delete this
|
|
* exception statement from your version.
|
|
*/
|
|
|
|
package com.ivmaisoft.jcgo;
|
|
|
|
/**
|
|
* This class maps Java names to C valid ones.
|
|
*/
|
|
|
|
final class NameMapper {
|
|
|
|
private static final String[] reservedPrefixArr = {
|
|
"CHKALL_", "ERROR_", "GC_", "HAVE_", "JCGO_", "JNI_", "Java_",
|
|
"MAXT_", "NOJAVA_", "OBJT_", "PTHREAD_", "_", "jcgo_" };
|
|
|
|
private static final String[] reservedSuffixArr = {
|
|
"_", "_methods", "_s", "_t" };
|
|
|
|
private static final String[] specClassSignsMap = {
|
|
Names.JAVA_LANG_CLASS, "c", Names.JAVA_LANG_OBJECT, "o",
|
|
Names.JAVA_LANG_STRING, "s", Names.JAVA_LANG_THROWABLE, "t" };
|
|
|
|
private final ObjHashtable shortLowNames = new ObjHashtable();
|
|
|
|
private final ObjHashtable usedNames = new ObjHashtable();
|
|
|
|
private final ObjHashtable methodCNames = new ObjHashtable();
|
|
|
|
private final ObjHashtable classVarCNames = new ObjHashtable();
|
|
|
|
private final ObjHashtable localVarCNames = new ObjHashtable();
|
|
|
|
NameMapper() {
|
|
tablePutKeys(shortLowNames, Names.specShortLowNameArr);
|
|
tablePutKeys(usedNames, Names.reservCNameArr);
|
|
}
|
|
|
|
private static void tablePutKeys(ObjHashtable table, String[] keys) {
|
|
int len = keys.length;
|
|
for (int i = 0; i < len; i++) {
|
|
table.put(keys[i], "");
|
|
}
|
|
}
|
|
|
|
String classToSign(String name) {
|
|
String[] signsMap = specClassSignsMap;
|
|
for (int i = signsMap.length - 1; i > 0; i -= 2) {
|
|
if (name.equals(signsMap[i - 1]))
|
|
return signsMap[i];
|
|
}
|
|
return hashToPackedStr(hashString(name), 5);
|
|
}
|
|
|
|
private static int hashString(String str) {
|
|
SecHashAlg sha = new SecHashAlg();
|
|
sha.updateUTF(str);
|
|
sha.finishUpdate();
|
|
return sha.engineDigestVal(null);
|
|
}
|
|
|
|
private static String hashToPackedStr(int value, int len) {
|
|
char[] chars = new char[len];
|
|
if (len > 0) {
|
|
int pos = len;
|
|
while (--pos > 0) {
|
|
int digit = value;
|
|
value = (value >>> 1) / 18;
|
|
digit -= value * 36;
|
|
chars[pos] = (char) ((digit < 10 ? '0' : 'a' - 10) + digit);
|
|
}
|
|
chars[0] = (char) ((value - ((value >>> 1) / 5) * 10) + '0');
|
|
}
|
|
return new String(chars);
|
|
}
|
|
|
|
String cnameToShort(String cname) {
|
|
String basename = cname;
|
|
int pos = cname.length();
|
|
while ((pos = basename.lastIndexOf('_', pos - 1)) >= 0) {
|
|
if (basename.length() - pos > 3
|
|
&& isLetter(basename.charAt(pos + 1))) {
|
|
basename = basename.substring(pos + 1);
|
|
break;
|
|
}
|
|
basename = basename.substring(0, pos) + basename.substring(pos + 1);
|
|
}
|
|
String shortname = shortenName(basename, 8);
|
|
String lowername = toLowerCase(shortname);
|
|
pos = shortname.length();
|
|
String cname2;
|
|
if (pos <= 1
|
|
|| ((cname2 = (String) shortLowNames.get(lowername)) != null && !cname2
|
|
.equals(cname)) || lowername.startsWith("jcgo")) {
|
|
int hash = hashString(cname);
|
|
if (pos >= 6) {
|
|
pos = 6;
|
|
}
|
|
do {
|
|
shortname = shortenName(basename, pos)
|
|
+ ConstValue.toPaddedHex(hash, true).substring(pos);
|
|
lowername = toLowerCase(shortname);
|
|
if (!lowername.startsWith("jcgo")
|
|
&& ((cname2 = (String) shortLowNames.get(lowername)) == null || cname2
|
|
.equals(cname)))
|
|
break;
|
|
if (pos > 3 || ++hash == 0) {
|
|
pos--;
|
|
}
|
|
} while (pos > 0);
|
|
}
|
|
shortLowNames.put(lowername, cname);
|
|
return shortname;
|
|
}
|
|
|
|
static boolean isLetter(char ch) {
|
|
return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
|
|
}
|
|
|
|
private static String toLowerCase(String str) {
|
|
char[] chars = str.toCharArray();
|
|
int i = chars.length;
|
|
boolean replaced = false;
|
|
char ch;
|
|
while (i-- > 0) {
|
|
if ((ch = chars[i]) >= 'A' && ch <= 'Z') {
|
|
chars[i] = (char) (ch + ('a' - 'A'));
|
|
replaced = true;
|
|
}
|
|
}
|
|
return replaced ? new String(chars) : str;
|
|
}
|
|
|
|
private static String shortenName(String str, int maxlen) {
|
|
char[] chars = str.toCharArray();
|
|
int len = chars.length;
|
|
if (len > maxlen) {
|
|
int i;
|
|
int j = len;
|
|
for (i = len; i > 1; i--) {
|
|
char ch = chars[i - 1];
|
|
if (ch >= 'A' && ch <= 'Z' && j - i >= len - maxlen)
|
|
break;
|
|
if (ch != 'a' && ch != 'e' && ch != 'i' && ch != 'o'
|
|
&& ch != 'u' && ch != 'y') {
|
|
chars[--j] = ch;
|
|
}
|
|
}
|
|
if (j > i && j < len) {
|
|
System.arraycopy(chars, j, chars, i, len - j);
|
|
}
|
|
len -= j - i;
|
|
if (len > maxlen) {
|
|
j = len;
|
|
for (i = len; i > 1; i--) {
|
|
if (j - i >= len - maxlen)
|
|
break;
|
|
char ch = chars[i - 1];
|
|
if ((ch >= 'A' && ch <= 'Z')
|
|
|| (chars[i - 2] >= 'A' && chars[i - 2] <= 'Z')) {
|
|
chars[--j] = ch;
|
|
}
|
|
}
|
|
if (j > i && j < len) {
|
|
System.arraycopy(chars, j, chars, i, len - j);
|
|
}
|
|
len -= j - i;
|
|
if (len >= maxlen) {
|
|
len = maxlen;
|
|
}
|
|
}
|
|
}
|
|
if (len > 0) {
|
|
char ch = chars[0];
|
|
if (ch >= 'a' && ch <= 'z') {
|
|
chars[0] = (char) (ch - ('a' - 'A'));
|
|
}
|
|
int i = len;
|
|
while (--i > 0) {
|
|
if ((ch = chars[i]) >= 'a' && ch <= 'z')
|
|
break;
|
|
}
|
|
if (i == 0)
|
|
while (++i < len) {
|
|
if ((ch = chars[i]) >= 'A' && ch <= 'Z') {
|
|
chars[i] = (char) (ch + ('a' - 'A'));
|
|
}
|
|
}
|
|
}
|
|
return new String(chars, 0, len);
|
|
}
|
|
|
|
private static String convertInvalidChars(String id) {
|
|
int len = id.length();
|
|
StringBuffer sb = new StringBuffer(len + 1);
|
|
boolean changed = false;
|
|
sb.append('0');
|
|
for (int pos = 0; pos < len; pos++) {
|
|
char ch = id.charAt(pos);
|
|
if (ch != '_' && (ch < '0' || ch > '9') && (ch < 'A' || ch > 'Z')
|
|
&& (ch < 'a' || ch > 'z')) {
|
|
sb.append(Integer.toHexString(ch));
|
|
changed = true;
|
|
} else {
|
|
sb.append(ch);
|
|
}
|
|
}
|
|
return changed ? sb.toString() : id;
|
|
}
|
|
|
|
private String convertId(String id) {
|
|
String name = convertInvalidChars(id.replace('$', '_')
|
|
.replace('.', '_'));
|
|
boolean changed = false;
|
|
if (name.length() > 0) {
|
|
char ch = name.charAt(0);
|
|
if (ch >= '0' && ch <= '9') {
|
|
name = "x" + name;
|
|
changed = true;
|
|
}
|
|
}
|
|
int i = reservedPrefixArr.length;
|
|
while (i-- > 0) {
|
|
if (name.startsWith(reservedPrefixArr[i])) {
|
|
name = "a" + name;
|
|
changed = true;
|
|
break;
|
|
}
|
|
}
|
|
i = reservedSuffixArr.length;
|
|
while (i-- > 0) {
|
|
if (name.endsWith(reservedSuffixArr[i])) {
|
|
changed = true;
|
|
break;
|
|
}
|
|
}
|
|
i = name.length() - 1;
|
|
while ((i = name.lastIndexOf('_', i)) > 0) {
|
|
int j = i;
|
|
do {
|
|
i--;
|
|
} while (name.charAt(i) == '_');
|
|
if (j - i > 1) {
|
|
name = name.substring(0, i + 1) + name.substring(j);
|
|
changed = true;
|
|
}
|
|
}
|
|
if (changed) {
|
|
name += hashToPackedStr(hashString(id), 3);
|
|
}
|
|
return name;
|
|
}
|
|
|
|
String classToCName(String name) {
|
|
if (name.indexOf('.', 0) < 0) {
|
|
name = "package." + name;
|
|
}
|
|
String cname = convertId(name);
|
|
String name2 = (String) usedNames.get(cname);
|
|
if (name2 != null && !name2.equals(name)) {
|
|
cname = cname + "_" + hashToPackedStr(hashString(name), 3);
|
|
while ((name2 = (String) usedNames.get(cname)) != null
|
|
&& !name2.equals(name)) {
|
|
cname = cname + "0";
|
|
}
|
|
}
|
|
usedNames.put(cname, name);
|
|
return cname;
|
|
}
|
|
|
|
String nameToJniName(String name) {
|
|
int pos = -1;
|
|
while ((pos = name.indexOf('_', pos + 1) + 1) > 0) {
|
|
name = name.substring(0, pos) + "1" + name.substring(pos);
|
|
}
|
|
while ((pos = name.indexOf('$', pos)) >= 0) {
|
|
name = name.substring(0, pos) + "_00024" + name.substring(pos + 1);
|
|
pos += 5;
|
|
}
|
|
return name.replace('.', '_');
|
|
}
|
|
|
|
String nameToProxyNamePart(String name) {
|
|
int pos = -1;
|
|
while ((pos = name.indexOf('$', pos + 1) + 1) > 0) {
|
|
name = name.substring(0, pos) + "$" + name.substring(pos);
|
|
}
|
|
pos = -1;
|
|
while ((pos = name.indexOf('.', pos + 1) + 1) > 0) {
|
|
name = name.substring(0, pos - 1) + "$0" + name.substring(pos);
|
|
}
|
|
return "$00" + name;
|
|
}
|
|
|
|
ObjQueue decodeProxyClassName(String className) {
|
|
className = className.substring(className.lastIndexOf('.') + 1);
|
|
if (!className.startsWith("$Proxy$00"))
|
|
return className.equals("$Proxy") ? new ObjQueue() : null;
|
|
ObjQueue ifaceNames = new ObjQueue();
|
|
className = className.substring(9);
|
|
do {
|
|
int next = className.indexOf("$00");
|
|
String name = next >= 0 ? className.substring(0, next) : className;
|
|
if (name.length() == 0)
|
|
return null;
|
|
int pos = -1;
|
|
while ((pos = name.indexOf("$0", pos + 1)) >= 0) {
|
|
name = name.substring(0, pos) + "." + name.substring(pos + 2);
|
|
}
|
|
pos = -1;
|
|
while ((pos = name.indexOf("$$", pos + 1)) >= 0) {
|
|
name = name.substring(0, pos) + name.substring(pos + 1);
|
|
}
|
|
ifaceNames.addLast(name);
|
|
if (next < 0)
|
|
break;
|
|
className = className.substring(next + 3);
|
|
} while (true);
|
|
return ifaceNames;
|
|
}
|
|
|
|
String methodToCSign(String id, String jsign, String parmCSign,
|
|
int hiddenCount, String classCName) {
|
|
if (hiddenCount > 0) {
|
|
id = id + "$0" + Integer.toString(hiddenCount + 1);
|
|
}
|
|
String csign = convertId(id) + parmCSign;
|
|
do {
|
|
String fullname = classCName != null ? classCName + "__" + csign
|
|
: csign;
|
|
String jsign2 = (String) methodCNames.get(fullname);
|
|
if (jsign2 == null) {
|
|
methodCNames.put(fullname, jsign);
|
|
break;
|
|
}
|
|
if (jsign2.equals(jsign))
|
|
break;
|
|
csign = csign + "0";
|
|
} while (true);
|
|
return csign;
|
|
}
|
|
|
|
String classVarToOutputName(String classCName, String originalName) {
|
|
String outputName = convertId(originalName.endsWith("_")
|
|
&& originalName.length() > 1 ? originalName.substring(0,
|
|
originalName.length() - 1) : originalName);
|
|
do {
|
|
String fullname = classCName + "__" + outputName;
|
|
String name2 = (String) classVarCNames.get(fullname);
|
|
if (name2 == null) {
|
|
if (usedNames.get(outputName) == null) {
|
|
classVarCNames.put(fullname, originalName);
|
|
break;
|
|
}
|
|
} else if (name2.equals(originalName))
|
|
break;
|
|
outputName += "0";
|
|
} while (true);
|
|
return outputName;
|
|
}
|
|
|
|
String localVarToOutputName(String classCName, String originalName) {
|
|
String outputName = convertId(originalName.startsWith("this_")
|
|
|| originalName.startsWith("val_") ? "_" + originalName
|
|
: originalName);
|
|
classCName = classCName + ".";
|
|
String cname;
|
|
String name2;
|
|
if (usedNames.get(outputName) != null
|
|
|| ((name2 = (String) localVarCNames.get(cname = classCName
|
|
+ outputName)) != null && !name2.equals(originalName))) {
|
|
outputName = outputName + "_"
|
|
+ hashToPackedStr(hashString(originalName), 3);
|
|
while (usedNames.get(outputName) != null
|
|
|| ((name2 = (String) localVarCNames.get(cname = classCName
|
|
+ outputName)) != null && !name2
|
|
.equals(originalName))) {
|
|
outputName += "0";
|
|
}
|
|
}
|
|
if (name2 == null) {
|
|
localVarCNames.put(cname, originalName);
|
|
}
|
|
return outputName;
|
|
}
|
|
|
|
String fieldToOutputName(ClassDefinition aclass, String originalName,
|
|
int hiddenCount) {
|
|
String outputName = convertId((originalName.startsWith("this_")
|
|
|| originalName.startsWith("val_") ? "_" : "")
|
|
+ (originalName.endsWith("_") && originalName.length() > 1 ? originalName
|
|
.substring(0, originalName.length() - 1) : originalName)
|
|
+ (hiddenCount > 0 ? "$0" + Integer.toString(hiddenCount + 1)
|
|
: ""));
|
|
if (usedNames.get(outputName) != null
|
|
|| !aclass.addFieldOutputName(outputName)) {
|
|
outputName = outputName + "_"
|
|
+ hashToPackedStr(hashString(originalName), 3);
|
|
while (usedNames.get(outputName) != null
|
|
|| !aclass.addFieldOutputName(outputName)) {
|
|
outputName += "0";
|
|
}
|
|
}
|
|
return outputName;
|
|
}
|
|
}
|