deep-c-rsc/JCGO/jtrsrc/com/ivmaisoft/jcgo/NameMapper.java
2021-07-16 17:12:20 -05:00

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;
}
}