提交 00981064 编写于 作者: T tbell

Merge

......@@ -116,8 +116,16 @@ CFLAGS_REQUIRED_sparcv9 += -m64 -mcpu=v9
LDFLAGS_COMMON_sparcv9 += -m64 -mcpu=v9
CFLAGS_REQUIRED_sparc += -m32 -mcpu=v9
LDFLAGS_COMMON_sparc += -m32 -mcpu=v9
CFLAGS_REQUIRED = $(CFLAGS_REQUIRED_$(ARCH))
LDFLAGS_COMMON += $(LDFLAGS_COMMON_$(ARCH))
ifeq ($(ZERO_BUILD), true)
CFLAGS_REQUIRED = $(ZERO_ARCHFLAG)
ifeq ($(ZERO_ENDIANNESS), little)
CFLAGS_REQUIRED += -D_LITTLE_ENDIAN
endif
LDFLAGS_COMMON += $(ZERO_ARCHFLAG)
else
CFLAGS_REQUIRED = $(CFLAGS_REQUIRED_$(ARCH))
LDFLAGS_COMMON += $(LDFLAGS_COMMON_$(ARCH))
endif
# If this is a --hash-style=gnu system, use --hash-style=both
# The gnu .hash section won't work on some Linux systems like SuSE 10.
......@@ -217,7 +225,7 @@ endif
EXTRA_LIBS += -lc
LDFLAGS_DEFS_OPTION = -z defs
LDFLAGS_DEFS_OPTION = -Xlinker -z -Xlinker defs
LDFLAGS_COMMON += $(LDFLAGS_DEFS_OPTION)
#
......
......@@ -667,12 +667,7 @@ LDLIBS = $(OTHER_LDLIBS) $(LDLIBS_$(VARIANT)) $(LDLIBS_COMMON)
LINTFLAGS = $(LINTFLAGS_$(VARIANT)) $(LINTFLAGS_COMMON) \
$(OTHER_LINTFLAGS)
# this should be moved into Defs-<platform>.gmk.....
ifeq ($(PLATFORM), windows)
VERSION_DEFINES = -DRELEASE="\"$(RELEASE)\""
else
VERSION_DEFINES = -DRELEASE='"$(RELEASE)"'
endif
VERSION_DEFINES = -DRELEASE='"$(RELEASE)"'
# Note: As a rule, GNU Make rules should not appear in any of the
# Defs*.gmk files. These were added for Kestrel-Solaris and do address
......
......@@ -85,7 +85,7 @@ ifneq (,$(findstring $(PLATFORM), linux solaris)) # UNIX systems
endif
endif
ifeq ($(PLATFORM), linux)
LDFLAGS += -z origin
LDFLAGS += -Wl,-z -Wl,origin
LDFLAGS += -Wl,--allow-shlib-undefined
LDFLAGS += -Wl,-rpath -Wl,\$$ORIGIN/../lib/$(LIBARCH)/jli
LDFLAGS += -Wl,-rpath -Wl,\$$ORIGIN/../jre/lib/$(LIBARCH)/jli
......@@ -236,13 +236,13 @@ endif # files
endif # INCREMENTAL_BUILD
ifdef JAVA_ARGS
OTHER_CPPFLAGS += -DJAVA_ARGS=$(JAVA_ARGS)
OTHER_CPPFLAGS += -DLAUNCHER_NAME=\"$(LAUNCHER_NAME)\"
OTHER_CPPFLAGS += -DJAVA_ARGS='$(JAVA_ARGS)'
OTHER_CPPFLAGS += -DLAUNCHER_NAME='"$(LAUNCHER_NAME)"'
endif
ifeq ($(PLATFORM), windows)
ifdef RELEASE
OTHER_CPPFLAGS += -DVERSION="$(RELEASE)"
OTHER_CPPFLAGS += -DVERSION='"$(RELEASE)"'
endif
endif
......@@ -258,14 +258,8 @@ endif
OTHER_INCLUDES += -I$(LAUNCHER_SHARE_SRC)/bin -I$(LAUNCHER_PLATFORM_SRC)/bin
OTHER_INCLUDES += -I$(SHARE_SRC)/native/java/util/zip/zlib-1.1.3
# this may not be necessary...
ifeq ($(PLATFORM), windows)
OTHER_CPPFLAGS += -DPROGNAME="\"$(PROGRAM)\""
VERSION_DEFINES += -DFULL_VERSION="\"$(FULL_VERSION)\""
else
OTHER_CPPFLAGS += -DPROGNAME='"$(PROGRAM)"'
VERSION_DEFINES += -DFULL_VERSION='"$(FULL_VERSION)"'
endif
VERSION_DEFINES += -DJDK_MAJOR_VERSION='"$(JDK_MAJOR_VERSION)"' \
-DJDK_MINOR_VERSION='"$(JDK_MINOR_VERSION)"'
......@@ -279,8 +273,14 @@ $(OBJDIR)/main.$(OBJECT_SUFFIX): $(LAUNCHER_SHARE_SRC)/bin/main.c
#
# How to install jvm.cfg.
#
$(JVMCFG): $(LAUNCHER_PLATFORM_SRC)/bin/$(ARCH)/jvm.cfg
#
ifeq ($(ZERO_BUILD), true)
JVMCFG_ARCH = zero
else
JVMCFG_ARCH = $(ARCH)
endif
$(JVMCFG): $(LAUNCHER_PLATFORM_SRC)/bin/$(JVMCFG_ARCH)/jvm.cfg
$(install-file)
#
......
......@@ -330,7 +330,7 @@ endif
#
# Specific files and directories that will be filtered out from above areas.
#
SOURCE_FILTERs = $(SCM_DIRs) 'X-*' '*-X-*' '*-template.java' ',*'
SOURCE_FILTERs = $(SCM_DIRs) ',*'
SOURCE_FILES_filter = $(SOURCE_FILTERs:%=-name % -prune -o)
#
......
......@@ -63,7 +63,7 @@ endif
# If AUTO_FILES_PROPERTIES_DIRS used, automatically find properties files
#
ifdef AUTO_FILES_PROPERTIES_DIRS
AUTO_FILES_PROPERTIES_FILTERS1 = $(SCM_DIRs) 'X-*' '*-X-*' ',*'
AUTO_FILES_PROPERTIES_FILTERS1 = $(SCM_DIRs) ',*'
AUTO_FILES_PROPERTIES_FILTERS1 += $(AUTO_PROPERTIES_PRUNE)
FILES_properties_find_filters1 = $(AUTO_FILES_PROPERTIES_FILTERS1:%=-name % -prune -o)
FILES_properties_auto1 := \
......@@ -111,7 +111,7 @@ include $(JDK_TOPDIR)/make/common/internal/Resources.gmk
ifdef AUTO_FILES_JAVA_DIRS
# Filter out these files or directories
AUTO_FILES_JAVA_SOURCE_FILTERS1 = $(SCM_DIRs) 'X-*' '*-X-*' '*-template.java' ',*'
AUTO_FILES_JAVA_SOURCE_FILTERS1 = $(SCM_DIRs) ',*'
AUTO_FILES_JAVA_SOURCE_FILTERS2 =
AUTO_FILES_JAVA_SOURCE_FILTERS1 += $(AUTO_JAVA_PRUNE)
AUTO_FILES_JAVA_SOURCE_FILTERS2 += $(AUTO_JAVA_PRUNE)
......
......@@ -109,7 +109,7 @@ else
LDFLAGS += -R \$$ORIGIN/jli
endif
ifeq ($(PLATFORM), linux)
LDFLAGS += -z origin
LDFLAGS += -Wl,-z -Wl,origin
LDFLAGS += -Wl,--allow-shlib-undefined
LDFLAGS += -Wl,-rpath -Wl,\$$ORIGIN/jli
endif
......
......@@ -48,11 +48,15 @@ ZIP_SRC = $(SHARE_SRC)/native/java/util/zip/zlib-$(ZLIB_VERSION)
LAUNCHER_SHARE_SRC = $(SHARE_SRC)/bin
LAUNCHER_PLATFORM_SRC = $(PLATFORM_SRC)/bin
ifeq ($(ZERO_BUILD), true)
ERGO_FAMILY=zero
else
ifeq ($(ARCH_FAMILY), amd64)
ERGO_FAMILY=i586
else
ERGO_FAMILY=$(ARCH_FAMILY)
endif
endif
#
......
......@@ -57,7 +57,7 @@ endif
#
include $(BUILDDIR)/common/Program.gmk
OTHER_CPPFLAGS += -DEXPAND_CLASSPATH_WILDCARDS
OTHER_CPPFLAGS += -DLAUNCHER_NAME=\"$(LAUNCHER_NAME)\"
OTHER_CPPFLAGS += -DLAUNCHER_NAME='"$(LAUNCHER_NAME)"'
ifeq ($(PLATFORM), solaris)
LDFLAGS += -R$(OPENWIN_LIB)
......
......@@ -62,4 +62,5 @@ endif
#
include $(BUILDDIR)/common/Program.gmk
OTHER_CPPFLAGS += -DEXPAND_CLASSPATH_WILDCARDS
OTHER_CPPFLAGS += -DLAUNCHER_NAME=\"$(LAUNCHER_NAME)\"
OTHER_CPPFLAGS += -DLAUNCHER_NAME='"$(LAUNCHER_NAME)"'
此差异已折叠。
......@@ -154,7 +154,7 @@ if [ $BIN ]; then
mv $DST $DST.tmp
sed -e '/#BIN/,$d' <$DST.tmp >$DST
rm -f $DST.tmp
binops=`dirname $SRC`/`basename $SRC .java`-bin.java
binops=`dirname $SRC`/`basename $SRC .java.template`-bin.java.template
genBinOps char character 1 two one $binops >>$DST
genBinOps short short 1 two one $binops >>$DST
genBinOps int integer 2 four three $binops >>$DST
......
......@@ -94,11 +94,13 @@ ifeq ($(INCLUDE_SA), true)
endif
endif # INCLUDE_SA
# Hotspot client is only available on 32-bit builds
# Hotspot client is only available on 32-bit non-Zero builds
ifneq ($(ZERO_BUILD), true)
ifeq ($(ARCH_DATA_MODEL), 32)
IMPORT_LIST += $(LIB_LOCATION)/$(CLIENT_LOCATION)/$(JVM_NAME) \
$(LIB_LOCATION)/$(CLIENT_LOCATION)/Xusage.txt
endif
endif
ifeq ($(PLATFORM), windows)
# Windows vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv Windows
......@@ -171,6 +173,7 @@ ifeq ($(PLATFORM), solaris)
IMPORT_LIST += $(LIB_LOCATION)/$(SERVER_LOCATION)/$(JVMDB_NAME)
endif
ifneq ($(ZERO_BUILD), true)
ifeq ($(ARCH_DATA_MODEL), 32)
IMPORT_LIST += $(LIB_LOCATION)/$(CLIENT_LOCATION)/$(LIBJSIG_NAME)
......@@ -201,6 +204,8 @@ endif # 32bit solaris
endif # 32bit
endif # ZERO_BUILD
# NOT Windows ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ NOT Windows
endif # PLATFORM
......
......@@ -33,7 +33,7 @@ include $(BUILDDIR)/common/Defs.gmk
all build: $(GENSRCDIR)/sun/misc/Version.java
$(GENSRCDIR)/sun/misc/Version.java: \
$(SHARE_SRC)/classes/sun/misc/Version-template.java
$(SHARE_SRC)/classes/sun/misc/Version.java.template
$(prep-target)
$(RM) $@.temp
$(SED) -e 's/@@launcher_name@@/$(LAUNCHER_NAME)/g' \
......
......@@ -128,7 +128,7 @@ endif # PLATFORM solaris
# for dynamic inclusion of extra sound libs: these
# JNI libs will be loaded from Platform.java
CPPFLAGS += -DEXTRA_SOUND_JNI_LIBS="\"$(EXTRA_SOUND_JNI_LIBS)\""
CPPFLAGS += -DEXTRA_SOUND_JNI_LIBS='"$(EXTRA_SOUND_JNI_LIBS)"'
# integrate MIDI i/o in jsound lib
ifeq ($(INCLUDE_MIDI),TRUE)
......
......@@ -55,21 +55,25 @@ ifeq ($(PLATFORM), solaris)
endif # PLATFORM solaris
ifeq ($(ARCH), i586)
CPPFLAGS += -DX_ARCH=X_I586
endif # ARCH i586
ifeq ($(ARCH), sparc)
CPPFLAGS += -DX_ARCH=X_SPARC
endif # ARCH sparc
ifeq ($(ARCH), sparcv9)
CPPFLAGS += -DX_ARCH=X_SPARCV9
endif # ARCH sparcv9
ifeq ($(ARCH), amd64)
CPPFLAGS += -DX_ARCH=X_AMD64
endif # ARCH amd64
ifeq ($(ZERO_BUILD), true)
CPPFLAGS += -DX_ARCH=X_ZERO
else
ifeq ($(ARCH), i586)
CPPFLAGS += -DX_ARCH=X_I586
endif # ARCH i586
ifeq ($(ARCH), sparc)
CPPFLAGS += -DX_ARCH=X_SPARC
endif # ARCH sparc
ifeq ($(ARCH), sparcv9)
CPPFLAGS += -DX_ARCH=X_SPARCV9
endif # ARCH sparcv9
ifeq ($(ARCH), amd64)
CPPFLAGS += -DX_ARCH=X_AMD64
endif # ARCH amd64
endif
# files needed for MIDI i/o
......
......@@ -339,3 +339,82 @@ fi
PATH="${path4sdk}"
export PATH
# Export variables required for Zero
if [ "${ZERO_BUILD}" = true ] ; then
# ZERO_LIBARCH is the name of the architecture-specific
# subdirectory under $JAVA_HOME/jre/lib
arch=$(uname -m)
case "${arch}" in
x86_64) ZERO_LIBARCH=amd64 ;;
i?86) ZERO_LIBARCH=i386 ;;
sparc64) ZERO_LIBARCH=sparcv9 ;;
arm*) ZERO_LIBARCH=arm ;;
*) ZERO_LIBARCH="$(arch)"
esac
export ZERO_LIBARCH
# ARCH_DATA_MODEL is the number of bits in a pointer
case "${ZERO_LIBARCH}" in
i386|ppc|s390|sparc|arm)
ARCH_DATA_MODEL=32
;;
amd64|ppc64|s390x|sparcv9|ia64|alpha)
ARCH_DATA_MODEL=64
;;
*)
echo "ERROR: Unable to determine ARCH_DATA_MODEL for ${ZERO_LIBARCH}"
exit 1
esac
export ARCH_DATA_MODEL
# ZERO_ENDIANNESS is the endianness of the processor
case "${ZERO_LIBARCH}" in
i386|amd64|ia64)
ZERO_ENDIANNESS=little
;;
ppc*|s390*|sparc*|alpha)
ZERO_ENDIANNESS=big
;;
*)
echo "ERROR: Unable to determine ZERO_ENDIANNESS for ${ZERO_LIBARCH}"
exit 1
esac
export ZERO_ENDIANNESS
# ZERO_ARCHDEF is used to enable architecture-specific code
case "${ZERO_LIBARCH}" in
i386) ZERO_ARCHDEF=IA32 ;;
ppc*) ZERO_ARCHDEF=PPC ;;
s390*) ZERO_ARCHDEF=S390 ;;
sparc*) ZERO_ARCHDEF=SPARC ;;
*) ZERO_ARCHDEF=$(echo "${ZERO_LIBARCH}" | tr a-z A-Z)
esac
export ZERO_ARCHDEF
# ZERO_ARCHFLAG tells the compiler which mode to build for
case "${ZERO_LIBARCH}" in
s390)
ZERO_ARCHFLAG="-m31"
;;
*)
ZERO_ARCHFLAG="-m${ARCH_DATA_MODEL}"
esac
export ZERO_ARCHFLAG
# LIBFFI_CFLAGS and LIBFFI_LIBS tell the compiler how to compile and
# link against libffi
pkgconfig=$(which pkg-config 2>/dev/null)
if [ -x "${pkgconfig}" ] ; then
if [ "${LIBFFI_CFLAGS}" = "" ] ; then
LIBFFI_CFLAGS=$("${pkgconfig}" --cflags libffi)
fi
if [ "${LIBFFI_LIBS}" = "" ] ; then
LIBFFI_LIBS=$("${pkgconfig}" --libs libffi)
fi
fi
if [ "${LIBFFI_LIBS}" = "" ] ; then
LIBFFI_LIBS="-lffi"
fi
export LIBFFI_CFLAGS
export LIBFFI_LIBS
fi
......@@ -137,15 +137,15 @@ ifeq ($(PROGRAM),jdb)
# PROGRAM, JAVA_ARGS, and APP_CLASSPATH are used in src/share/bin/java.c
# SA is currently not available on windows (for any ARCH), or linux-ia64:
ifneq ($(ARCH), ia64)
JDB_CLASSPATH = "{ \"/lib/tools.jar\", \"/lib/sa-jdi.jar\", \"/classes\" }"
OTHER_CPPFLAGS += -DAPP_CLASSPATH=$(JDB_CLASSPATH)
JDB_CLASSPATH = { "/lib/tools.jar", "/lib/sa-jdi.jar", "/classes" }
OTHER_CPPFLAGS += -DAPP_CLASSPATH='$(JDB_CLASSPATH)'
endif
endif
# jconsole only
ifeq ($(PROGRAM),jconsole)
JCONSOLE_CLASSPATH = "{ \"/lib/jconsole.jar\", \"/lib/tools.jar\", \"/classes\" }"
OTHER_CPPFLAGS += -DAPP_CLASSPATH=$(JCONSOLE_CLASSPATH)
JCONSOLE_CLASSPATH = { "/lib/jconsole.jar", "/lib/tools.jar", "/classes" }
OTHER_CPPFLAGS += -DAPP_CLASSPATH='$(JCONSOLE_CLASSPATH)'
ifeq ($(PLATFORM), windows)
OTHER_CPPFLAGS += -DJAVAW
LDLIBS_COMMON += user32.lib
......@@ -163,8 +163,8 @@ endif
# SA tools need special app classpath
ifeq ($(SA_TOOL),true)
SA_CLASSPATH = "{ \"/lib/tools.jar\", \"/lib/sa-jdi.jar\", \"/classes\"}"
OTHER_CPPFLAGS += -DAPP_CLASSPATH=$(SA_CLASSPATH)
SA_CLASSPATH = { "/lib/tools.jar", "/lib/sa-jdi.jar", "/classes" }
OTHER_CPPFLAGS += -DAPP_CLASSPATH='$(SA_CLASSPATH)'
endif
# Wildcards
......@@ -173,11 +173,11 @@ ifeq ($(WILDCARDS),true)
endif
# Always tell native code what the main class is
OTHER_CPPFLAGS += -DMAIN_CLASS=\"$(MAIN_CLASS)\"
OTHER_CPPFLAGS += -DMAIN_CLASS='"$(MAIN_CLASS)"'
# Construct initializer for initial arguments to java
ALL_ARGS = -J-ms8m $(MAIN_JAVA_ARGS) $(MAIN_CLASS) $(MAIN_ARGS)
JAVA_ARGS = "{ $(ALL_ARGS:%=\"%\",) }"
JAVA_ARGS = { $(ALL_ARGS:%="%",) }
# Always report launcher info
build: launcher_info
......
......@@ -33,7 +33,7 @@ includes=\
com/sun/tools/jconsole/ \
sun/tools/jconsole/
excludes=\
sun/tools/jconsole/Version-template.java
sun/tools/jconsole/Version.java.template
jtreg.tests=\
sun/tools/jconsole/
javadoc.packagenames=\
......
......@@ -35,7 +35,7 @@
<target name="-pre-compile">
<copy
file="${root}/src/share/classes/sun/tools/jconsole/Version-template.java"
file="${root}/src/share/classes/sun/tools/jconsole/Version.java.template"
tofile="${gensrc.dir}/sun/tools/jconsole/Version.java"/>
<replace
file="${gensrc.dir}/sun/tools/jconsole/Version.java"
......
......@@ -70,7 +70,7 @@ include $(BUILDDIR)/common/Classes.gmk
build: $(FILES_png) $(FILES_gif) $(TEMPDIR)/manifest $(JARFILE)
$(GENSRCDIR)/sun/tools/jconsole/Version.java: \
$(SHARE_SRC)/classes/sun/tools/jconsole/Version-template.java
$(SHARE_SRC)/classes/sun/tools/jconsole/Version.java.template
$(MKDIR) -p $(@D)
$(SED) -e 's/@@jconsole_version@@/$(FULL_VERSION)/g' $< > $@
......
......@@ -44,14 +44,6 @@ include $(BUILDDIR)/common/Defs.gmk
include FILES_java.gmk
AUTO_FILES_JAVA_DIRS = sun/nio/cs/ext
# Exclude a few sources on windows
ifeq ($(PLATFORM), windows)
AUTO_JAVA_PRUNE = sun/nio/cs/ext/COMPOUND_TEXT.java \
sun/nio/cs/ext/COMPOUND_TEXT_Decoder.java \
sun/nio/cs/ext/COMPOUND_TEXT_Encoder.java \
sun/nio/cs/ext/CompoundTextSupport.java
endif # PLATFORM
# For Cygwin, command line arguments that are paths must be converted to
# windows style paths. These paths cannot be used as targets, however, because
# the ":" in them will interfere with GNU Make rules, generating "multiple
......
......@@ -38,7 +38,6 @@ SUBDIRS = \
compile_properties \
dir_diff \
dtdbuilder \
fontchecker \
freetypecheck \
generate_break_iterator \
GenerateCharacter \
......
/*
* Copyright 2002-2004 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package build.tools.fontchecker;
import java.awt.*;
import java.awt.image.*;
import java.io.*;
/**
* FontCheckDummy (not unlike Crash Test Dummy).
*
* <PRE>
* FontCheckDummy is the "child" process. Its task is to verify
* integrity of system fonts. Since unexpected crashes are known
* to occur when certain fonts are manipulated, the process is
* "monitored" by the parent process, which might have to restart
* the "child" if it crashes.
* </PRE>
*
* @author Ilya Bagrak
*/
public class FontCheckDummy implements FontCheckerConstants {
/**
* Input stream from parent process.
*/
private BufferedReader is;
/**
* Output stream to parent process.
*/
private BufferedOutputStream os;
/**
* Image on which font characters will be drawn.
*/
private BufferedImage bi;
/**
* graphics object on which characters will be drawn.
*/
private Graphics graphics;
/**
* This constructor wraps the process's standard output and input streams
* to enable easier communication with parent process. It also initializes
* the graphics object used for drawing font characters.
* <BR><BR>
* @see FontCheckerConstants
*/
public FontCheckDummy() {
is = new BufferedReader(new InputStreamReader(System.in));
os = new BufferedOutputStream(System.out);
/* make suffficient space for 12 point font */
bi = new BufferedImage(40, 40, BufferedImage.TYPE_INT_RGB);
graphics = bi.getGraphics();
try {
os.write(CHILD_STARTED_OK);
os.flush();
} catch (IOException e) {
System.exit(-1);
}
}
/**
* Initializes an instance of Font from given font path.
* <BR>
* This methods attempts to create an instance of font from
* a string that represents path to the font file.
* <BR><BR>
* @param fontPath string representing path to font file
* @param flag indicating whether or not checking of non-TrueType fonts
* is necessary
*/
private void testFont(String fontPath, boolean checkNonTTF) {
FontFileFilter fff = new FontFileFilter(checkNonTTF);
File fontFile = new File(fontPath);
if (!fontFile.canRead()) {
try {
os.write(ERR_FONT_NOT_FOUND);
os.flush();
} catch (IOException e) {
System.exit(-1);
}
}
Font font = null;
try {
File file = new File(fontPath);
font = Font.createFont(fff.getFontType(fontPath), file);
} catch (FontFormatException e1) {
} catch (IOException e2) {
}
if (font == null) {
return;
}
font = font.deriveFont(Font.PLAIN, 12);
String name = font.getFontName();
String family = font.getFamily();
char[] testChars = { '0' };
if (font.canDisplay(testChars[0])) {
graphics.setFont(font);
graphics.drawChars(testChars, 0, 1, 20, 20);
}
try {
os.write(ERR_FONT_OK);
os.flush();
} catch (IOException e) {
System.exit(-1);
}
}
/**
* Begins synchronous communication betweeen parent and child processes.
* <BR>
* This method begins communication between parent and child processes.
* FontCheckDummy reads a line of text from input stream (@see #is).
*/
public void run() {
String command = null;
while (true) {
try {
command = is.readLine();
} catch (IOException e) {
System.exit(-1);
}
if (command != null && command.length() >= 1) {
int cmd = Integer.parseInt(command.substring(0,1));
if (cmd == EXITCOMMAND) {
return;
}
boolean checkNonTTF = ((cmd == 1) ? true : false);
String fontPath = command.substring(1);
testFont(fontPath, checkNonTTF);
} else {
return;
}
}
}
public static void main(String[] args) {
try {
/* Background app. */
System.setProperty("java.awt.headless", "true");
System.setProperty("sun.java2d.noddraw", "true");
new FontCheckDummy().run();
} catch (Throwable t) {
}
System.exit(0);
}
}
/*
* Copyright 2002-2004 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package build.tools.fontchecker;
import java.io.*;
import java.util.*;
import java.awt.event.*;
import sun.font.FontManager;
/**
* FontChecker.
*
* <PRE>
* This is a FontChecker program. This class is a "parent" process
* which invokes a "child" process. The child process will test
* series of fonts and may crash as it encounters invalid fonts.
* The "parent" process must then interpret error codes passed to it
* by the "child" process and restart the "child" process if necessary.
*
* usage: java FontChecker [-v] -o outputfile
*
* -o is the name of the file to contains canonical path names of
* bad fonts that are identified. This file is not created if
* no bad fonts are found.
* -v verbose: prints progress messages.
*
* </PRE>
*
* @author Ilya Bagrak
*/
public class FontChecker implements ActionListener, FontCheckerConstants {
/**
* Output stream to subprocess.
* Corresponds to the subprocess's System.in".
*/
private PrintWriter procPipeOut;
/**
* Input stream from subprocess.
* Corresponds to the subprocess's System.out".
*/
private BufferedInputStream procPipeIn;
/**
* Child process.
*/
private Process childProc;
/**
* Name of output file to write file names of bad fonts
*/
private String outputFile;
/**
* Reference to currently executing thread.
*/
private Thread currThread;
/**
* Timeout timer for a single font check
*/
private javax.swing.Timer timeOne;
/**
* Timeout timer for all font checks
*/
private javax.swing.Timer timeAll;
/**
* max time (in milliseconds) allowed for checking a single font.
*/
private static int timeoutOne = 10000;
/**
* max time (in milliseconds) allowed for checking all fonts.
*/
private static int timeoutAll = 120000;
/**
* Boolean flag indicating whether FontChecker is required to
* check non-TrueType fonts.
*/
private boolean checkNonTTF = false;
/**
* List of bad fonts found in the system.
*/
private Vector badFonts = new Vector();
/**
* whether to print warnings messges etc to stdout/err
* default is false
*/
private static boolean verbose = false;
/* Command to use to exec sub-process. */
private static String javaCmd = "java";
static void printlnMessage(String s) {
if (verbose) {
System.out.println(s);
}
}
/**
* Event handler for timer event.
* <BR>
* Stops the timer and interrupts the current thread which is
* still waiting on I/O from the child process.
* <BR><BR>
* @param evt timer event
*/
public void actionPerformed(ActionEvent evt) {
if (evt.getSource() == timeOne) {
timeOne.stop();
printlnMessage("Child timed out: killing");
childProc.destroy();
} else {
doExit(); // went on too long (ie timeAll timed out).
}
}
/**
* Initializes a FontChecker.
* <BR>
* This method is usually called after an unrecoverable error has
* been detected and a child process has either crashed or is in bad
* state. The method creates a new child process from
* scratch and initializes it's input/output streams.
*/
public void initialize() {
try {
if (childProc != null) {
childProc.destroy();
}
String fileSeparator = System.getProperty("file.separator");
String javaHome = System.getProperty("java.home");
String classPath = System.getProperty("java.class.path");
classPath = "\"" + classPath + "\"";
String opt = "-cp " + classPath + " -Dsun.java2d.fontpath=\"" +
javaHome + fileSeparator + "lib" + fileSeparator + "fonts\"";
/* command to exec the child process with the same JRE */
String cmd =
new String(javaHome + fileSeparator + "bin" +
fileSeparator + javaCmd +
" -XXsuppressExitMessage " + opt +
" com.sun.java2d.fontchecker.FontCheckDummy");
printlnMessage("cmd="+cmd);
childProc = Runtime.getRuntime().exec(cmd);
} catch (IOException e) {
printlnMessage("can't execute child process");
System.exit(0);
} catch (SecurityException e) {
printlnMessage("Error: access denied");
System.exit(0);
}
/* initialize input/output streams to/from child process */
procPipeOut = new PrintWriter(childProc.getOutputStream());
procPipeIn = new BufferedInputStream(childProc.getInputStream());
try {
int code = procPipeIn.read();
if (code != CHILD_STARTED_OK) {
printlnMessage("bad child process start status="+code);
doExit();
}
} catch (IOException e) {
printlnMessage("can't read child process start status unknown");
doExit();
}
}
private void doExit() {
try {
if (procPipeOut != null) {
/* Tell the child to exit */
procPipeOut.write(EXITCOMMAND+System.getProperty("line.separator"));
procPipeOut.flush();
procPipeOut.close();
}
} catch (Throwable t) {
}
System.exit(0);
}
/**
* Tries to verify integrity of a font specified by a path.
* <BR>
* This method is used to test whether a font specified by the given
* path is valid and does not crash the system.
* <BR><BR>
* @param fontPath a string representation of font path
* to standard out during while this font is tried
* @return returns <code>true</code> if font is OK, and
* <code>false</code> otherwise.
*/
public boolean tryFont(File fontFile) {
int bytesRead = 0;
String fontPath = fontFile.getAbsolutePath();
printlnMessage("Checking font "+fontPath);
/* store reference to the current thread, so that when the timer
* fires it can be interrupted
*/
currThread = Thread.currentThread();
timeOne.restart();
/* write a string command out to child process
* The command is formed by appending whether to test non-TT fonts
* and font path to be tested
*/
String command = Integer.toString(checkNonTTF ? 1 : 0) +
fontPath +
System.getProperty("line.separator");
procPipeOut.write(command);
procPipeOut.flush();
/* check if underlying stream has encountered an error after
* command has been issued
*/
if (procPipeOut.checkError()){
printlnMessage("Error: font crashed");
initialize();
return false;
}
/* trying reading error code back from child process */
try {
bytesRead = procPipeIn.read();
} catch(InterruptedIOException e) {
/* A timeout timer fired before the operation completed */
printlnMessage("Error: timeout occured");
initialize();
return false;
} catch(IOException e) {
/* there was an error reading from the stream */
timeOne.stop();
printlnMessage("Error: font crashed");
initialize();
return false;
} catch (Throwable t) {
bytesRead = ERR_FONT_READ_EXCPT;
} finally {
timeOne.stop();
}
if (bytesRead == ERR_FONT_OK) {
printlnMessage("Font integrity verified");
return true;
} else if (bytesRead > 0) {
switch(bytesRead){
case ERR_FONT_NOT_FOUND:
printlnMessage("Error: font not found!");
break;
case ERR_FONT_BAD_FORMAT:
printlnMessage("Error: incorrect font format");
break;
case ERR_FONT_READ_EXCPT:
printlnMessage("Error: exception reading font");
break;
case ERR_FONT_DISPLAY:
printlnMessage("Error: can't display characters");
break;
case ERR_FONT_CRASH:
printlnMessage("Error: font crashed");
break;
default:
printlnMessage("Error: invalid error code:"+bytesRead);
break;
}
} else if (bytesRead == ERR_FONT_EOS) {
printlnMessage("Error: end of stream marker encountered");
} else {
printlnMessage("Error: invalid error code:"+bytesRead);
}
/* if we still haven't returned from this method, some error
* condition has occured and it is safer to re-initialize
*/
initialize();
return false;
}
/**
* Checks the integrity of all system fonts.
* <BR>
* This method goes through every font in system's font path and verifies
* its integrity via the tryFont method.
* <BR><BR>
* @param restart <code>true</code> if checking of fonts should continue
* after the first bad font is found, and <code>false</code> otherwise
* @return returns <code>true</code> if all fonts are valid,
* <code>false</code> otherwise
* @see #tryFont(String, boolean, boolean)
*/
public boolean checkFonts(boolean restart) {
/* file filter to filter out none-truetype font files */
FontFileFilter fff = new FontFileFilter(checkNonTTF);
boolean checkOk = true;
/* get platform-independent font path. Note that this bypasses
* the normal GraphicsEnvironment initialisation. In conjunction with
* the headless setting above, so we want to add
* java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment();
* to trigger a more normal initialisation.
*/
java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment();
String fontPath = FontManager.getFontPath(true);
StringTokenizer st =
new StringTokenizer(fontPath,
System.getProperty("path.separator"));
/* some systems may have multiple font paths separated by
* platform-dependent characters, so fontPath string needs to be
* parsed
*/
timeOne = new javax.swing.Timer(timeoutOne, this);
timeAll = new javax.swing.Timer(timeoutAll, this);
timeAll.restart();
while (st.hasMoreTokens()) {
File fontRoot = new File(st.nextToken());
File[] fontFiles = fontRoot.listFiles(fff);
for (int i = 0; i < fontFiles.length; i++) {
/* for each font file that is not a directory and passes
* through the font filter run the test
*/
if (!fontFiles[i].isDirectory() &&
!tryFont(fontFiles[i])) {
checkOk = false;
badFonts.add(fontFiles[i].getAbsolutePath());
if (!restart) {
break;
}
}
}
}
/* Tell the child to exit */
procPipeOut.write(EXITCOMMAND+System.getProperty("line.separator"));
procPipeOut.flush();
procPipeOut.close();
return checkOk;
}
public static void main(String args[]){
try {
/* Background app. */
System.setProperty("java.awt.headless", "true");
System.setProperty("sun.java2d.noddraw", "true");
boolean restart = true;
boolean errorFlag = false;
FontChecker fc = new FontChecker();
int arg = 0;
while (arg < args.length && errorFlag == false) {
if (args[arg].equals("-v")) {
verbose = true;
}
else if (args[arg].equals("-w") &&
System.getProperty("os.name", "unknown").
startsWith("Windows")) {
javaCmd = "javaw";
}
else if (args[arg].equals("-o")) {
/* set output file */
if (++arg < args.length)
fc.outputFile = args[arg];
else {
/* invalid argument format */
printlnMessage("Error: invalid argument format");
errorFlag = true;
}
}
else {
/* invalid command line argument */
printlnMessage("Error: invalid argument value");
errorFlag = true;
}
arg++;
}
if (errorFlag || fc.outputFile == null) {
System.exit(0);
}
File outfile = new File(fc.outputFile);
if (outfile.exists()) {
outfile.delete();
}
fc.initialize();
if (!fc.checkFonts(restart)) {
String[] badFonts = (String[])fc.badFonts.toArray(new String[0]);
if (badFonts.length > 0) {
printlnMessage("Bad Fonts:");
try {
FileOutputStream fos =
new FileOutputStream(fc.outputFile);
PrintStream ps = new PrintStream(fos);
for (int i = 0; i < badFonts.length; i++) {
ps.println(badFonts[i]);
printlnMessage(badFonts[i]);
}
fos.close();
} catch (IOException e) {
}
}
} else {
printlnMessage("No bad fonts found.");
}
} catch (Throwable t) {
}
System.exit(0);
}
}
/*
* Copyright 2002-2003 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* <PRE>
* This class filters TrueType font files from other file
* found in the font path.
*
* </PRE>
*
* @author Ilya Bagrak
*/
package build.tools.fontchecker;
import java.awt.*;
import java.io.*;
public class FontFileFilter implements java.io.FileFilter, FontCheckerConstants {
/**
* Boolean flag indicating whether this filter filters out
* non-TrueType fonts.
*/
private boolean checkNonTTF;
public FontFileFilter() {
this(false);
}
public FontFileFilter(boolean checkNonTTF) {
super();
this.checkNonTTF = checkNonTTF;
}
/**
* Checks whether a file is accepted by this filter.
* <BR>
* This method checks whehter a file is accepted by this filter.
* This filter is made to accept all the file whose extension is
* either .ttf or .TTF. These files are assumed to be TrueType fonts.
* <BR><BR>
* @return returns a boolean value indicating whether or not a file is
* accepted
*/
public boolean accept(File pathname) {
String name = pathname.getName();
return (name.endsWith(".ttf") ||
name.endsWith(".TTF") ||
name.endsWith(".ttc") ||
name.endsWith(".TTC")) ||
(name.endsWith(".pfb") ||
name.endsWith(".PFB") ||
name.endsWith(".pfa") ||
name.endsWith(".PFA") &&
checkNonTTF == true);
}
public static int getFontType(String filename) {
if (filename.endsWith(".ttf") ||
filename.endsWith(".TTF") ||
filename.endsWith(".ttc") ||
filename.endsWith(".TTC"))
return Font.TRUETYPE_FONT;
else if (filename.endsWith(".pfb") ||
filename.endsWith(".PFB") ||
filename.endsWith(".pfa") ||
filename.endsWith(".PFA"))
return Font.TYPE1_FONT;
else
return 999;
}
}
/*
* Copyright 2002-2003 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
Instructions for running FontChecker
------------------------------------
FontChecker is a program designed to identify fonts that may cause JRE
crashes. Such fonts may be corrupted files, or badly constructed fonts.
Some crashes may also be due to bugs in the JRE's font code.
This test is designed to run quickly and silently as part of the JRE
installation process. It will only benefit users who install the JRE
via that mechanism. It cannot guarantee to identify all "bad fonts" because
the tests are minimal. Nor can it prevent problems due to fonts installed
subsequently to the JRE's installation. However it does ensure that the
vast majority of problem fonts are identified. This is important
"RAS" functionality. It is targeted at the consumer/plugin market where
there is substantial likelihood of end-users having installed software
packages which may be delivered with fonts that are not up to commercial
standards.
The test is designed to be "fail safe". If the program fails to run
properly it has no impact on the installer or on JRE execution.
Thus there is no need to monitor successful execution of the test.
The test is not a new "tool" in the sense of "javah" etc.
The test is not designed to be user executable or visible, and should
be unpacked by the installer into a temporary location, and executed
once the rest of the JRE is installed (ie as a postinstall step), and
can then be deleted from the temporary location once installation is
complete. Not deleting the jar file before execution is complete is
probably the sole reason that the installer may want to wait for
the program to complete.
The FontChecker application can be run directly from the jar
file with this command:
%java -jar fontchecker.jar -o <file>
The output file is a required parameter in this version of the application.
The JRE installer should use the above form, and use it to create an
output file which must be named "badfonts.txt" and be placed into
the JRE's lib\fonts directory eg:-
java -jar fontchecker.jar -o "C:\Program Files\jre\lib\fonts\badfonts.txt"
Note the lower case "badfonts.txt", and the string quotes because of the spaces
in the path name.
The location given here is an example and needs to be calculated at install
time as $JREHOME\lib\fonts\badfonts.txt
The location and name are important, because the JRE at runtime will
look for this exactly located name and file.
This location is private to that JRE instance. It will not affect
any other JRE installed on the system.
If running from a different directory than that containing the jar file,
use the form containing the full path to the jar file, eg :
java -jar C:\fc\fontchecker.jar -o "C:\Program Files\jre\lib\fonts\badfonts.txt"
FontChecker application accepts following command line flags.
usage: java -jar fontchecker.jar -o outputfile
-v
-o is the name of the file to contains canonical path names of
bad fonts that are identified. This file is not created if
no bad fonts are found.
-v verbose mode: print progress/warning messages. Not recommended
for installer use.
-w if running on Windows, use "javaw" to exec the sub-process.
......@@ -38,6 +38,7 @@
#define X_SPARCV9 3
#define X_IA64 4
#define X_AMD64 5
#define X_ZERO 6
// **********************************
// Make sure you set X_PLATFORM and X_ARCH defines correctly.
......
/*
* Copyright 2002-2004 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1998-2007 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -22,24 +22,37 @@
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
#include "ergo.h"
package build.tools.fontchecker;
public interface FontCheckerConstants {
/* Methods for solaris-sparc and linux-sparc: these are easy. */
/* code sent to indicate child process started OK */
public static final int CHILD_STARTED_OK = 100;
/* Ask the OS how many processors there are. */
static unsigned long
physical_processors(void) {
const unsigned long sys_processors = sysconf(_SC_NPROCESSORS_CONF);
/* error codes returned from child process */
public static final int ERR_FONT_OK = 65;
public static final int ERR_FONT_NOT_FOUND = 60;
public static final int ERR_FONT_BAD_FORMAT = 61;
public static final int ERR_FONT_READ_EXCPT = 62;
public static final int ERR_FONT_DISPLAY = 64;
public static final int ERR_FONT_EOS = -1;
/* nl char sent after child crashes */
public static final int ERR_FONT_CRASH = 10;
JLI_TraceLauncher("sysconf(_SC_NPROCESSORS_CONF): %lu\n", sys_processors);
return sys_processors;
}
/* The sparc version of the "server-class" predicate. */
jboolean
ServerClassMachineImpl(void) {
jboolean result = JNI_FALSE;
/* How big is a server class machine? */
const unsigned long server_processors = 2UL;
const uint64_t server_memory = 2UL * GB;
const uint64_t actual_memory = physical_memory();
/* 0 and 1 are reserved, and commands can only be a single digit integer */
public static final int EXITCOMMAND = 2;
/* Is this a server class machine? */
if (actual_memory >= server_memory) {
const unsigned long actual_processors = physical_processors();
if (actual_processors >= server_processors) {
result = JNI_TRUE;
}
}
JLI_TraceLauncher("unix_" LIBARCHNAME "_ServerClassMachine: %s\n",
(result == JNI_TRUE ? "JNI_TRUE" : "JNI_FALSE"));
return result;
}
#
# Copyright 1998-2005 Sun Microsystems, Inc. All Rights Reserved.
# Copyright 2003 Sun Microsystems, Inc. All Rights Reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
......@@ -22,22 +21,19 @@
# CA 95054 USA or visit www.sun.com if you need additional information or
# have any questions.
#
#
# Makefile for building the fontchecker tool
#
BUILDDIR = ../..
PACKAGE = build.tools.fontchecker
PRODUCT = tools
PROGRAM = fontchecker
include $(BUILDDIR)/common/Defs.gmk
BUILDTOOL_SOURCE_ROOT = $(BUILDDIR)/tools/src
BUILDTOOL_MAIN = $(PKGDIR)/FontChecker.java
#
# Build tool jar rules.
#
include $(BUILDDIR)/common/BuildToolJar.gmk
#
# List of JVMs that can be used as an option to java, javac, etc.
# Order is important -- first in this list is the default JVM.
# NOTE that this both this file and its format are UNSUPPORTED and
# WILL GO AWAY in a future release.
#
# You may also select a JVM in an arbitrary location with the
# "-XXaltjvm=<jvm_dir>" option, but that too is unsupported
# and may not be available in a future release.
#
-server KNOWN
-client IGNORE
-hotspot ERROR
-classic WARN
-native ERROR
-green ERROR
......@@ -26,7 +26,7 @@
javac -d . ../../../../make/tools/src/build/tools/spp/Spp.java
gen() {
java build.tools.spp.Spp -K$1 -Dtype=$1 -DType=$2 -DFulltype=$3 <Basic-X.java >Basic$2.java
java build.tools.spp.Spp -K$1 -Dtype=$1 -DType=$2 -DFulltype=$3 <Basic-X.java.template >Basic$2.java
}
gen byte Byte Byte
......
......@@ -26,7 +26,7 @@
javac -d . ../../../../make/tools/src/build/tools/spp/Spp.java > Spp.java
gen() {
java build.tools.spp.Spp -K$1 -Dtype=$1 -DType=$2 -DFulltype=$3<CopyDirect-X-Memory.java >CopyDirect$2Memory.java
java build.tools.spp.Spp -K$1 -Dtype=$1 -DType=$2 -DFulltype=$3<CopyDirect-X-Memory.java.template >CopyDirect$2Memory.java
}
gen byte Byte Byte
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册