/*
*
*
* Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
*
* This program 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.
*
* 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 version 2 for more details (a copy is
* included at /legal/license.txt).
*
* 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 or visit www.sun.com if you need additional
* information or have any questions.
*/
package config;
import java.io.*;
import java.util.*;
import util.*;
/**
* The Configurator class deals with the creation of jvmconfig.h,
* which controls the build options of the VM (e.g.,
* ENABLE_JAVA_DEBUGGER, ENABLE_CLDC_11, etc).
*
* See src/vm/share/utilities/BuildFlags.hpp about how the content of
* jvmconfig.h is specified.
*/
public class Configurator {
Vector flags;
Hashtable platform;
Hashtable product;
public Configurator() {
}
/**
* Read input from platform file, which usually have contents like:
* os_family = linux
* arch = i386
* carch = thumb2
* iarch = c
* os_arch = linux_i386
* compiler = gcc
* cpu_variant =
*/
public void readPlatformFile(String infile) throws Exception {
platform = new Hashtable();
readConfigFile(infile, platform);
}
public void readProductFile(String infile) throws Exception {
product = new Hashtable();
readConfigFile(infile, product);
}
private void readConfigFile(String infile, Hashtable properties)
throws Exception {
FileInputStream in = new FileInputStream(infile);
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line;
while ((line = reader.readLine()) != null) {
StringTokenizer st = new StringTokenizer(line, "=");
String name = null;
String value = null;
try {
name = st.nextToken();
value = st.nextToken();
} catch (Throwable t) {;}
if (name == null) {
continue;
}
name = name.trim();
if (name.equals("")) {
continue;
}
if (value == null) {
value = "";
} else {
value = value.trim();
}
properties.put(name, value);
}
}
/**
* Read input from infile (usually BuildFlags.hpp)
*/
public void readInputFile(String infile) throws Exception {
FileInputStream in = new FileInputStream(infile);
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line;
boolean started = false;
EnableFlag currentFlag = null;
flags = new Vector();
while ((line = reader.readLine()) != null) {
if (line.indexOf("{{ ENABLE_FLAGS_BEGIN") >= 0) {
started = true;
} else if (line.indexOf("ENABLE_FLAGS_END }}") >= 0) {
break;
} else {
EnableFlag newFlag = tryStartFlag(line);
if (newFlag == null) {
if (currentFlag != null) {
addComments(currentFlag, line);
}
} else {
flags.addElement(newFlag);
currentFlag = newFlag;
}
}
}
}
/**
* Print a warning if an unknown ENABLE_XXX flag is specified in the
* env. This is probably a typo by the user.
*/
void checkSpuriousFlags(Hashtable env) {
boolean warned = false;
Vector names = getFlagNames();
for (Enumeration e = env.keys(); e.hasMoreElements() ;) {
String key = (String)e.nextElement();
if (key.startsWith("ENABLE_") && !key.endsWith("__BY")
&& !key.equals("ENABLE_MAP_FILE")
&& !names.contains(key)) {
if (!warned) {
System.out.println("*********");
warned = true;
}
System.out.println("Warning: unknown flag " + key);
}
}
if (warned) {
System.out.println("*********");
}
}
/**
* Write the output file. The env hashtable allows the user to specify
* alternative values for the configuration flags.
*/
public void write(String outfile, Hashtable env, Vector extra)
throws Exception
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintWriter writer = new PrintWriter(new OutputStreamWriter(baos));
byte data[];
checkSpuriousFlags(env);
writeConfigProlog(writer);
writePlatformFlags(writer);
writeEnableFlags(writer, env);
writeOptionDump(writer);
writeExtraFlags(writer, extra);
writeConfigEpilog(writer);
writer.flush();
data = baos.toByteArray();
writer.close();
writeFileIfNecessary(data, outfile);
}
public void writeFileIfNecessary(byte data[], String outfile)
throws Exception
{
boolean necessary = true;
File f = new File(outfile);
if (f.exists()) {
FileInputStream in = new FileInputStream(outfile);
byte savedData[] = new byte[in.available()];
if (in.read(savedData) == savedData.length) {
necessary = false;
for (int i=0; i<savedData.length; i++) {
if (data[i] != savedData[i]) {
necessary = true;
break;
}
}
}
in.close();
}
if (necessary) {
FileOutputStream out = new FileOutputStream(outfile);
out.write(data);
out.close();
} else {
System.out.println("jvmconfig.h has not changed");
}
}
public Vector getFlagNames() {
Vector v = new Vector();
for (int i=0; i<flags.size(); i++) {
EnableFlag flag = (EnableFlag)flags.elementAt(i);
v.addElement(flag.name);
}
return v;
}
public String getDefaultValue(String name) {
Vector v = new Vector();
for (int i=0; i<flags.size(); i++) {
EnableFlag flag = (EnableFlag)flags.elementAt(i);
if (flag.name.equals(name)) {
if (flag.debug.def != flag.product.def) {
throw new Error("Debug and product default values aren't "+
"same");
}
switch (flag.debug.def) {
case ALWAYS_DISABLE:
case DISABLE:
return "false";
default:
return "true";
}
}
}
throw new Error("Option \"" + name + "\" not found");
}
public String getProductName() {
return (String)product.get(PRODUCT_NAME_KEY);
}
public String getReleaseVersion() {
return (String)product.get(RELEASE_VERSION_KEY);
}
static final String PRODUCT_NAME_KEY = "PRODUCT_NAME";
static final String RELEASE_VERSION_KEY = "RELEASE_VERSION";
static final int ALWAYS_DISABLE = 1;
static final int DISABLE = 2;
static final int ENABLE = 3;
static final int ALWAYS_ENABLE = 4;
EnableFlag tryStartFlag(String line) {
StringTokenizer st = new StringTokenizer(line, " \t\n\r");
int tokenNumber = 0;
String name = null;
int debugDefault = -1000;
int productDefault = -1000;
String comments = "";
while (st.hasMoreTokens()) {
String token = st.nextToken();
switch (tokenNumber) {
case 0:
if (token.equals("//")) {
continue;
}
else if (token.startsWith("ENABLE_")) {
name = token;
tokenNumber ++;
continue;
} else {
return null;
}
case 1:
if (token.length() != 3) {
return null;
}
if (token.charAt(1) != ',') {
return null;
}
if ((debugDefault = getDefault(token.charAt(0))) < 0) {
return null;
}
if ((productDefault = getDefault(token.charAt(2))) < 0) {
return null;
}
tokenNumber ++;
break;
default:
if (token.indexOf("=====") < 0) {
comments = comments + " " + token;
}
}
}
if (tokenNumber <= 1) {
return null;
}
EnableFlag flag = new EnableFlag();
flag.name = name;
flag.debug.def = debugDefault;
flag.product.def = productDefault;
flag.comments = comments;
return flag;
}
void addComments(EnableFlag flag, String line) {
StringTokenizer st = new StringTokenizer(line, " \t\n\r");
String comments = "";
while (st.hasMoreTokens()) {
String token = st.nextToken();
if (token.equals("//") && comments.equals("")) {
continue;
} else if (token.indexOf("=====") >= 0) {
continue;
} else {
comments = comments + " " + token;
}
}
if (comments.length() > 0) {
flag.comments += " " + comments;
}
}
int getDefault(char c) {
switch (c) {
case '-': return ALWAYS_DISABLE;
case '0': return DISABLE;
case '1': return ENABLE;
case '+': return ALWAYS_ENABLE;
default: return -1;
}
}
void writeConfigProlog(PrintWriter writer) throws Exception {
InputStream in =
Configurator.class.getResourceAsStream("config_prolog.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line;
while ((line = reader.readLine()) != null) {
writer.println(line);
}
in.close();
}
void writePlatformFlags(PrintWriter writer)
throws Exception
{
String arch = (String)platform.get("arch");
String iarch = (String)platform.get("iarch");
String carch = (String)platform.get("carch");
String compiler = (String)platform.get("compiler");
if (iarch == null || iarch.equals("")) {
iarch = arch;
}
if (carch == null || carch.equals("")) {
carch = arch;
}
writer.println();
writer.println("// BEGIN: Information derived from \"platform\" file");
if (carch.equals("arm") || iarch.equals("arm")) {
writer.println("#ifndef ARM");
writer.println("#define ARM 1");
writer.println("#endif");
}
else if (carch.equals("thumb2") || iarch.equals("thumb2")) {
writer.println("#ifndef ARM");
writer.println("#define ARM 1");
writer.println("#endif");
}
else if (carch.equals("sh") || iarch.equals("sh")) {
writer.println("#ifndef HITACHI_SH");
writer.println("#define HITACHI_SH1");
writer.println("#endif");
}
writer.println("#define INTERPRETER_ARCH_NAME \"" + iarch + "\"");
writer.println("// END: Information derived from \"platform\" file");
writer.println();
}
void writeEnableFlags(PrintWriter writer, Hashtable env)
throws Exception
{
for (int i=0; i<flags.size(); i++) {
EnableFlag flag = (EnableFlag)flags.elementAt(i);
writeFlag(writer, env, flag);
}
}
public void writeExtraFlags(PrintWriter writer, Vector extra)
throws Exception
{
for (int i=0; i<extra.size(); i++) {
String flag = (String)extra.elementAt(i);
flag = flag.replace('=', ' ');
writer.println();
writer.println("/* Extra flag for this build configuration */");
writer.println("#define " + flag);
}
}
void writeConfigEpilog(PrintWriter writer) throws Exception {
writer.println();
writer.println("#endif /* _JVM_CONFIG_H_ */");
writer.println();
}
void writeFlag(PrintWriter writer, Hashtable env, EnableFlag flag) {
writer.println();
writer.println("/" + "*\n * " + flag.name);
writer.print(" * ");
int linepos = 0;
StringTokenizer st = new StringTokenizer(flag.comments);
while (st.hasMoreTokens()) {
String token = st.nextToken();
if (linepos > 0 && token.length() + linepos > 60) {
writer.println();
writer.print(" * ");
linepos = 0;
}
writer.print(" ");
writer.print(token);
linepos += 1 + token.length();
}
writer.println();
writer.println(" *" + "/");
writer.println();
getValue(env, flag.name, flag.debug);
getValue(env, flag.name, flag.product);
if (flag.debug.value == flag.product.value &&
flag.debug.source.equals(flag.product.source)) {
writeValue(writer, flag.name, flag.debug);
} else {
writer.println("#ifndef PRODUCT");
writeValue(writer, flag.name, flag.debug);
writer.println("#else");
writeValue(writer, flag.name, flag.product);
writer.println("#endif");
}
}
void writeValue(PrintWriter writer, String name, FlagValue value) {
int i;
if (name.trim().equals("ENABLE_PCSL")) {
writer.println("#ifndef " + name);
}
writer.print("#define " + name + " ");
for (i=name.length() + 1; i<30; i++) {
writer.print(" ");
}
writer.println((value.value ? "1" : "0") +
" /* " + value.source + " */");
if (name.trim().equals("ENABLE_PCSL")) {
writer.println("#endif");
}
}
void getValue(Hashtable env, String name, FlagValue value) {
String envValue = (String)env.get(name);
String envSource = (String)env.get(name + "__BY");
boolean envDefault = false;
if (envValue != null) {
if (envValue.equals("true")) {
envDefault = true;
} else if (envValue.equals("false")) {
envDefault = false;
} else {
System.out.println("Bad value \"" + envValue +
"\" for env variable \"" + name +
"\"");
System.out.println("Must be \"true\" or \"false\".\n");
System.exit(0);
return;
}
}
switch (value.def) {
case ALWAYS_DISABLE:
value.value = false;
value.source = "Always disabled";
break;
case ALWAYS_ENABLE:
value.value = true;
value.source = "Always enabled";
break;
default:
if (envValue == null) {
value.value = (value.def == ENABLE);
value.source = "VM default: BuildFlags.hpp";
} else {
value.value = envDefault;
if ("idetool".equals(envSource)) {
value.source = "User setting in idetool";
} else if (envSource != null) {
if (!envSource.startsWith("configurator override:")) {
value.source = "Platform default: " + envSource;
} else {
value.source = envSource;
}
} else {
value.source = "User environment variable";
}
}
}
}
/**
* Writes the names and values of the flags into a table, so that
* it's easy for C code to dump the values of the flags (for debugging
* purposes).
*/
void writeOptionDump(PrintWriter writer) {
writer.println();
writer.println("/*");
writer.println(" * The following table is for dumping the flags");
writer.println(" * for debugging purposes.");
writer.println(" */");
writer.println();
writer.println("#ifndef PRODUCT");
writeDump(writer, flags, true);
writer.println("#else");
writeDump(writer, flags, false);
writer.println("#endif");
}
void writeDump(PrintWriter writer, Vector flags, boolean isDebug) {
writer.println("#define ENABLE_FLAG_VALUES { \\");
for (int i=0; i<flags.size(); i++) {
EnableFlag flag = (EnableFlag)flags.elementAt(i);
FlagValue value;
if (isDebug) {
value = flag.debug;
} else {
value = flag.product;
}
writer.print("\t\"" + flag.name + "\", ");
for (int j=flag.name.length(); j<30; j++) {
writer.print(" ");
}
if (value.value) {
writer.print("\"enabled\",");
} else {
writer.print("\"-\",");
}
writer.println(" \\");
}
writer.println("}");
}
}
class EnableFlag {
public String name;
public String comments;
public FlagValue debug;
public FlagValue product;
public EnableFlag() {
debug = new FlagValue();
product = new FlagValue();
}
}
class FlagValue {
public int def;
public String source;
public boolean value;
}
|