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 config;
028:
029: import java.io.*;
030: import java.util.*;
031: import util.*;
032:
033: /**
034: * The Configurator class deals with the creation of jvmconfig.h,
035: * which controls the build options of the VM (e.g.,
036: * ENABLE_JAVA_DEBUGGER, ENABLE_CLDC_11, etc).
037: *
038: * See src/vm/share/utilities/BuildFlags.hpp about how the content of
039: * jvmconfig.h is specified.
040: */
041: public class Configurator {
042: Vector flags;
043: Hashtable platform;
044: Hashtable product;
045:
046: public Configurator() {
047:
048: }
049:
050: /**
051: * Read input from platform file, which usually have contents like:
052: * os_family = linux
053: * arch = i386
054: * carch = thumb2
055: * iarch = c
056: * os_arch = linux_i386
057: * compiler = gcc
058: * cpu_variant =
059: */
060: public void readPlatformFile(String infile) throws Exception {
061: platform = new Hashtable();
062:
063: readConfigFile(infile, platform);
064: }
065:
066: public void readProductFile(String infile) throws Exception {
067: product = new Hashtable();
068:
069: readConfigFile(infile, product);
070: }
071:
072: private void readConfigFile(String infile, Hashtable properties)
073: throws Exception {
074: FileInputStream in = new FileInputStream(infile);
075: BufferedReader reader = new BufferedReader(
076: new InputStreamReader(in));
077: String line;
078:
079: while ((line = reader.readLine()) != null) {
080: StringTokenizer st = new StringTokenizer(line, "=");
081: String name = null;
082: String value = null;
083:
084: try {
085: name = st.nextToken();
086: value = st.nextToken();
087: } catch (Throwable t) {
088: ;
089: }
090:
091: if (name == null) {
092: continue;
093: }
094: name = name.trim();
095: if (name.equals("")) {
096: continue;
097: }
098: if (value == null) {
099: value = "";
100: } else {
101: value = value.trim();
102: }
103:
104: properties.put(name, value);
105: }
106: }
107:
108: /**
109: * Read input from infile (usually BuildFlags.hpp)
110: */
111: public void readInputFile(String infile) throws Exception {
112: FileInputStream in = new FileInputStream(infile);
113: BufferedReader reader = new BufferedReader(
114: new InputStreamReader(in));
115:
116: String line;
117: boolean started = false;
118: EnableFlag currentFlag = null;
119: flags = new Vector();
120:
121: while ((line = reader.readLine()) != null) {
122: if (line.indexOf("{{ ENABLE_FLAGS_BEGIN") >= 0) {
123: started = true;
124: } else if (line.indexOf("ENABLE_FLAGS_END }}") >= 0) {
125: break;
126: } else {
127: EnableFlag newFlag = tryStartFlag(line);
128: if (newFlag == null) {
129: if (currentFlag != null) {
130: addComments(currentFlag, line);
131: }
132: } else {
133: flags.addElement(newFlag);
134: currentFlag = newFlag;
135: }
136: }
137: }
138: }
139:
140: /**
141: * Print a warning if an unknown ENABLE_XXX flag is specified in the
142: * env. This is probably a typo by the user.
143: */
144: void checkSpuriousFlags(Hashtable env) {
145: boolean warned = false;
146: Vector names = getFlagNames();
147: for (Enumeration e = env.keys(); e.hasMoreElements();) {
148: String key = (String) e.nextElement();
149: if (key.startsWith("ENABLE_") && !key.endsWith("__BY")
150: && !key.equals("ENABLE_MAP_FILE")
151: && !names.contains(key)) {
152: if (!warned) {
153: System.out.println("*********");
154: warned = true;
155: }
156: System.out.println("Warning: unknown flag " + key);
157: }
158: }
159:
160: if (warned) {
161: System.out.println("*********");
162: }
163: }
164:
165: /**
166: * Write the output file. The env hashtable allows the user to specify
167: * alternative values for the configuration flags.
168: */
169: public void write(String outfile, Hashtable env, Vector extra)
170: throws Exception {
171: ByteArrayOutputStream baos = new ByteArrayOutputStream();
172: PrintWriter writer = new PrintWriter(new OutputStreamWriter(
173: baos));
174: byte data[];
175:
176: checkSpuriousFlags(env);
177: writeConfigProlog(writer);
178: writePlatformFlags(writer);
179: writeEnableFlags(writer, env);
180: writeOptionDump(writer);
181: writeExtraFlags(writer, extra);
182: writeConfigEpilog(writer);
183: writer.flush();
184: data = baos.toByteArray();
185: writer.close();
186:
187: writeFileIfNecessary(data, outfile);
188: }
189:
190: public void writeFileIfNecessary(byte data[], String outfile)
191: throws Exception {
192: boolean necessary = true;
193:
194: File f = new File(outfile);
195: if (f.exists()) {
196: FileInputStream in = new FileInputStream(outfile);
197: byte savedData[] = new byte[in.available()];
198: if (in.read(savedData) == savedData.length) {
199: necessary = false;
200: for (int i = 0; i < savedData.length; i++) {
201: if (data[i] != savedData[i]) {
202: necessary = true;
203: break;
204: }
205: }
206: }
207: in.close();
208: }
209:
210: if (necessary) {
211: FileOutputStream out = new FileOutputStream(outfile);
212: out.write(data);
213: out.close();
214: } else {
215: System.out.println("jvmconfig.h has not changed");
216: }
217: }
218:
219: public Vector getFlagNames() {
220: Vector v = new Vector();
221: for (int i = 0; i < flags.size(); i++) {
222: EnableFlag flag = (EnableFlag) flags.elementAt(i);
223: v.addElement(flag.name);
224: }
225: return v;
226: }
227:
228: public String getDefaultValue(String name) {
229: Vector v = new Vector();
230: for (int i = 0; i < flags.size(); i++) {
231: EnableFlag flag = (EnableFlag) flags.elementAt(i);
232: if (flag.name.equals(name)) {
233: if (flag.debug.def != flag.product.def) {
234: throw new Error(
235: "Debug and product default values aren't "
236: + "same");
237: }
238: switch (flag.debug.def) {
239: case ALWAYS_DISABLE:
240: case DISABLE:
241: return "false";
242: default:
243: return "true";
244: }
245: }
246: }
247: throw new Error("Option \"" + name + "\" not found");
248: }
249:
250: public String getProductName() {
251: return (String) product.get(PRODUCT_NAME_KEY);
252: }
253:
254: public String getReleaseVersion() {
255: return (String) product.get(RELEASE_VERSION_KEY);
256: }
257:
258: static final String PRODUCT_NAME_KEY = "PRODUCT_NAME";
259: static final String RELEASE_VERSION_KEY = "RELEASE_VERSION";
260:
261: static final int ALWAYS_DISABLE = 1;
262: static final int DISABLE = 2;
263: static final int ENABLE = 3;
264: static final int ALWAYS_ENABLE = 4;
265:
266: EnableFlag tryStartFlag(String line) {
267: StringTokenizer st = new StringTokenizer(line, " \t\n\r");
268: int tokenNumber = 0;
269: String name = null;
270: int debugDefault = -1000;
271: int productDefault = -1000;
272: String comments = "";
273:
274: while (st.hasMoreTokens()) {
275: String token = st.nextToken();
276: switch (tokenNumber) {
277: case 0:
278: if (token.equals("//")) {
279: continue;
280: } else if (token.startsWith("ENABLE_")) {
281: name = token;
282: tokenNumber++;
283: continue;
284: } else {
285: return null;
286: }
287:
288: case 1:
289: if (token.length() != 3) {
290: return null;
291: }
292: if (token.charAt(1) != ',') {
293: return null;
294: }
295: if ((debugDefault = getDefault(token.charAt(0))) < 0) {
296: return null;
297: }
298: if ((productDefault = getDefault(token.charAt(2))) < 0) {
299: return null;
300: }
301: tokenNumber++;
302: break;
303:
304: default:
305: if (token.indexOf("=====") < 0) {
306: comments = comments + " " + token;
307: }
308: }
309: }
310:
311: if (tokenNumber <= 1) {
312: return null;
313: }
314:
315: EnableFlag flag = new EnableFlag();
316: flag.name = name;
317: flag.debug.def = debugDefault;
318: flag.product.def = productDefault;
319: flag.comments = comments;
320:
321: return flag;
322: }
323:
324: void addComments(EnableFlag flag, String line) {
325: StringTokenizer st = new StringTokenizer(line, " \t\n\r");
326: String comments = "";
327:
328: while (st.hasMoreTokens()) {
329: String token = st.nextToken();
330: if (token.equals("//") && comments.equals("")) {
331: continue;
332: } else if (token.indexOf("=====") >= 0) {
333: continue;
334: } else {
335: comments = comments + " " + token;
336: }
337: }
338: if (comments.length() > 0) {
339: flag.comments += " " + comments;
340: }
341: }
342:
343: int getDefault(char c) {
344: switch (c) {
345: case '-':
346: return ALWAYS_DISABLE;
347: case '0':
348: return DISABLE;
349: case '1':
350: return ENABLE;
351: case '+':
352: return ALWAYS_ENABLE;
353: default:
354: return -1;
355: }
356: }
357:
358: void writeConfigProlog(PrintWriter writer) throws Exception {
359: InputStream in = Configurator.class
360: .getResourceAsStream("config_prolog.txt");
361: BufferedReader reader = new BufferedReader(
362: new InputStreamReader(in));
363: String line;
364:
365: while ((line = reader.readLine()) != null) {
366: writer.println(line);
367: }
368: in.close();
369: }
370:
371: void writePlatformFlags(PrintWriter writer) throws Exception {
372: String arch = (String) platform.get("arch");
373: String iarch = (String) platform.get("iarch");
374: String carch = (String) platform.get("carch");
375: String compiler = (String) platform.get("compiler");
376:
377: if (iarch == null || iarch.equals("")) {
378: iarch = arch;
379: }
380: if (carch == null || carch.equals("")) {
381: carch = arch;
382: }
383:
384: writer.println();
385: writer
386: .println("// BEGIN: Information derived from \"platform\" file");
387:
388: if (carch.equals("arm") || iarch.equals("arm")) {
389: writer.println("#ifndef ARM");
390: writer.println("#define ARM 1");
391: writer.println("#endif");
392: } else if (carch.equals("thumb2") || iarch.equals("thumb2")) {
393: writer.println("#ifndef ARM");
394: writer.println("#define ARM 1");
395: writer.println("#endif");
396: } else if (carch.equals("sh") || iarch.equals("sh")) {
397: writer.println("#ifndef HITACHI_SH");
398: writer.println("#define HITACHI_SH1");
399: writer.println("#endif");
400: }
401:
402: writer.println("#define INTERPRETER_ARCH_NAME \"" + iarch
403: + "\"");
404: writer
405: .println("// END: Information derived from \"platform\" file");
406: writer.println();
407: }
408:
409: void writeEnableFlags(PrintWriter writer, Hashtable env)
410: throws Exception {
411: for (int i = 0; i < flags.size(); i++) {
412: EnableFlag flag = (EnableFlag) flags.elementAt(i);
413: writeFlag(writer, env, flag);
414: }
415:
416: }
417:
418: public void writeExtraFlags(PrintWriter writer, Vector extra)
419: throws Exception {
420: for (int i = 0; i < extra.size(); i++) {
421: String flag = (String) extra.elementAt(i);
422: flag = flag.replace('=', ' ');
423: writer.println();
424: writer
425: .println("/* Extra flag for this build configuration */");
426: writer.println("#define " + flag);
427: }
428: }
429:
430: void writeConfigEpilog(PrintWriter writer) throws Exception {
431: writer.println();
432: writer.println("#endif /* _JVM_CONFIG_H_ */");
433: writer.println();
434: }
435:
436: void writeFlag(PrintWriter writer, Hashtable env, EnableFlag flag) {
437: writer.println();
438: writer.println("/" + "*\n * " + flag.name);
439: writer.print(" * ");
440:
441: int linepos = 0;
442: StringTokenizer st = new StringTokenizer(flag.comments);
443: while (st.hasMoreTokens()) {
444: String token = st.nextToken();
445: if (linepos > 0 && token.length() + linepos > 60) {
446: writer.println();
447: writer.print(" * ");
448: linepos = 0;
449: }
450: writer.print(" ");
451: writer.print(token);
452: linepos += 1 + token.length();
453: }
454: writer.println();
455: writer.println(" *" + "/");
456: writer.println();
457:
458: getValue(env, flag.name, flag.debug);
459: getValue(env, flag.name, flag.product);
460:
461: if (flag.debug.value == flag.product.value
462: && flag.debug.source.equals(flag.product.source)) {
463: writeValue(writer, flag.name, flag.debug);
464: } else {
465: writer.println("#ifndef PRODUCT");
466: writeValue(writer, flag.name, flag.debug);
467: writer.println("#else");
468: writeValue(writer, flag.name, flag.product);
469: writer.println("#endif");
470: }
471: }
472:
473: void writeValue(PrintWriter writer, String name, FlagValue value) {
474: int i;
475: if (name.trim().equals("ENABLE_PCSL")) {
476: writer.println("#ifndef " + name);
477: }
478: writer.print("#define " + name + " ");
479: for (i = name.length() + 1; i < 30; i++) {
480: writer.print(" ");
481: }
482: writer.println((value.value ? "1" : "0") + " /* "
483: + value.source + " */");
484: if (name.trim().equals("ENABLE_PCSL")) {
485: writer.println("#endif");
486: }
487: }
488:
489: void getValue(Hashtable env, String name, FlagValue value) {
490: String envValue = (String) env.get(name);
491: String envSource = (String) env.get(name + "__BY");
492: boolean envDefault = false;
493:
494: if (envValue != null) {
495: if (envValue.equals("true")) {
496: envDefault = true;
497: } else if (envValue.equals("false")) {
498: envDefault = false;
499: } else {
500: System.out.println("Bad value \"" + envValue
501: + "\" for env variable \"" + name + "\"");
502: System.out.println("Must be \"true\" or \"false\".\n");
503: System.exit(0);
504: return;
505: }
506: }
507:
508: switch (value.def) {
509: case ALWAYS_DISABLE:
510: value.value = false;
511: value.source = "Always disabled";
512: break;
513: case ALWAYS_ENABLE:
514: value.value = true;
515: value.source = "Always enabled";
516: break;
517: default:
518: if (envValue == null) {
519: value.value = (value.def == ENABLE);
520: value.source = "VM default: BuildFlags.hpp";
521: } else {
522: value.value = envDefault;
523: if ("idetool".equals(envSource)) {
524: value.source = "User setting in idetool";
525: } else if (envSource != null) {
526: if (!envSource.startsWith("configurator override:")) {
527: value.source = "Platform default: " + envSource;
528: } else {
529: value.source = envSource;
530: }
531: } else {
532: value.source = "User environment variable";
533: }
534: }
535: }
536: }
537:
538: /**
539: * Writes the names and values of the flags into a table, so that
540: * it's easy for C code to dump the values of the flags (for debugging
541: * purposes).
542: */
543: void writeOptionDump(PrintWriter writer) {
544: writer.println();
545: writer.println("/*");
546: writer
547: .println(" * The following table is for dumping the flags");
548: writer.println(" * for debugging purposes.");
549: writer.println(" */");
550: writer.println();
551: writer.println("#ifndef PRODUCT");
552: writeDump(writer, flags, true);
553: writer.println("#else");
554: writeDump(writer, flags, false);
555: writer.println("#endif");
556: }
557:
558: void writeDump(PrintWriter writer, Vector flags, boolean isDebug) {
559: writer.println("#define ENABLE_FLAG_VALUES { \\");
560: for (int i = 0; i < flags.size(); i++) {
561: EnableFlag flag = (EnableFlag) flags.elementAt(i);
562: FlagValue value;
563: if (isDebug) {
564: value = flag.debug;
565: } else {
566: value = flag.product;
567: }
568: writer.print("\t\"" + flag.name + "\", ");
569: for (int j = flag.name.length(); j < 30; j++) {
570: writer.print(" ");
571: }
572: if (value.value) {
573: writer.print("\"enabled\",");
574: } else {
575: writer.print("\"-\",");
576: }
577: writer.println(" \\");
578: }
579: writer.println("}");
580: }
581: }
582:
583: class EnableFlag {
584: public String name;
585: public String comments;
586: public FlagValue debug;
587: public FlagValue product;
588:
589: public EnableFlag() {
590: debug = new FlagValue();
591: product = new FlagValue();
592: }
593: }
594:
595: class FlagValue {
596: public int def;
597: public String source;
598: public boolean value;
599: }
|