ICU-4460 make taglet work for both 1.4 and 1.5

X-SVN-Rev: 17391
This commit is contained in:
Doug Felt 2005-03-25 17:44:29 +00:00
parent 1ef9ce4649
commit a67194865d
2 changed files with 239 additions and 6 deletions

View file

@ -0,0 +1,219 @@
/**
*******************************************************************************
* Copyright (C) 2004, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
package com.ibm.icu.dev.tool.docs;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.PrintStream;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* A simple facility for adding C-like preprocessing to .java files.
* This only understands a subset of the C preprocessing syntax.
* Its used to manage files that with only small differences can be
* compiled for different JVMs. Input is generally a '.jpp' file,
* output is a '.java' file with the same name, that can then be
* compiled.
*/
public class CodeMangler {
private String infile;
private String outfile;
private Map map;
private boolean verbose;
public static void main(String[] args) {
new CodeMangler(args).run();
}
private static final String usage = "Usage:\n" +
"-in[file] path - read from file, otherwise read stdin\n" +
"-out[file] path - write to output file, otherwise write stdout\n" +
"-d[efine] NAME[=VALUE] - define NAME with optional value VALUE\n" +
"\n" +
"directives in the file are one of the following:\n" +
" #ifdef, #ifndef, #else, #endif, #if, #elif, #define, #undef\n" +
"these may optionally be preceeded by whitespace or //.\n" +
"#if, #elif args are of the form 'key == value' or 'key != value'\n" +
"only exact character match key with value is performed.\n" +
"#define args are 'key [==] value', the '==' is optional\n";
CodeMangler(String[] args) {
map = new HashMap();
String arg = null;
try {
for (int i = 0; i < args.length; ++i) {
arg = args[i];
if (arg.startsWith("-in")) {
infile = args[++i];
} else if (arg.startsWith("-out")) {
outfile = args[++i];
} else if (arg.startsWith("-d")) {
String id = args[++i];
String val = "";
int ix = id.indexOf('=');
if (ix >= 0) {
val = id.substring(ix+1);
id = id.substring(0,ix);
}
map.put(id, val);
} else if (arg.startsWith("-help")) {
System.out.print(usage);
System.exit(0);
} else if (arg.startsWith("-v")) {
verbose = true;
} else {
System.err.println("Error: unrecognized argument '" + arg + "'");
System.err.println(usage);
System.exit(1);
}
}
} catch (IndexOutOfBoundsException e) {
System.err.println("Error: argument '" + arg + "' missing value");
System.err.println(usage);
System.exit(1);
}
}
public void run() {
Pattern pat = Pattern.compile(
"(?i)^\\s*(?://+)??\\s*#(ifdef\\s|ifndef\\s|else|endif|undef\\s|define\\s|if\\s|elif\\s)\\s*(.*)$");
Pattern pat2 = Pattern.compile("([^=!]+)\\s*([!=]=)??\\s*(\\w+)");
try {
PrintStream outstream = System.out;
if (outfile != null) {
outstream = new PrintStream(new FileOutputStream(outfile));
}
InputStream instream = System.in;
if (infile != null) {
instream = new FileInputStream(infile);
}
class State {
int lc;
String line;
boolean emit = true;
boolean tripped;
private State next;
public String toString() {
return "line " + lc
+ ": '" + line
+ "' (emit: " + emit
+ " tripped: " + tripped
+ ")";
}
void trip(boolean trip) {
if (!tripped & trip) {
tripped = true;
emit = next != null ? next.emit : true;
} else {
emit = false;
}
}
State push(int lc, String line, boolean trip) {
this.lc = lc;
this.line = line;
State ret = new State();
ret.next = this;
ret.emit = this.emit & trip;
ret.tripped = trip;
return ret;
}
State pop() {
return next;
}
}
BufferedReader reader = new BufferedReader(new InputStreamReader(instream));
String line = null;
int lc = 0;
State state = new State();
while ((line = reader.readLine()) != null) {
Matcher m = pat.matcher(line);
if (m.find()) {
String key = m.group(1).toLowerCase().trim();
String val = m.group(2).trim();
if (verbose) outstream.println("directive: " + line
+ " key: '" + key
+ "' val: '" + val
+ "' " + state);
if (key.equals("ifdef")) {
state = state.push(lc, line, map.get(val) != null);
} else if (key.equals("ifndef")) {
state = state.push(lc, line, map.get(val) == null);
} else if (key.equals("else")) {
state.trip(true);
} else if (key.equals("endif")) {
state = state.pop();
} else if (key.equals("undef")) {
if (state.emit) {
map.remove(val);
}
} else {
Matcher m2 = pat2.matcher(val);
if (m2.find()) {
String key2 = m2.group(1).trim();
boolean neq = "!=".equals(m2.group(2)); // optional
String val2 = m2.group(3).trim();
if (verbose) outstream.println("val2: '" + val2
+ "' neq: '" + neq
+ "' key2: '" + key2
+ "'");
if (key.equals("if")) {
state = state.push(lc, line, val2.equals(map.get(key2)) != neq);
} else if (key.equals("elif")) {
state.trip(val2.equals(map.get(key2)) != neq);
} else if (key.equals("define")) {
if (state.emit) {
map.put(key2, val2);
}
}
}
}
continue;
}
lc++;
if (state.emit) {
outstream.println(line);
} else {
if (verbose) outstream.println("skipping: " + line);
}
}
state = state.pop();
if (state != null) {
System.out.println("Error: unclosed directive(s):");
do {
System.err.println(state);
} while ((state = state.pop()) != null);
}
outstream.close();
instream.close();
}
catch (IOException e) {
System.out.println(e);
}
}
}

View file

@ -4,18 +4,28 @@
* others. All Rights Reserved. *
*******************************************************************************
*/
/**
* Preprocess with com.ibm.icu.dev.tool.docs.CodeMangler to generate
* either a JDK 1.4 or JDK 1.5 version. For the 1.5 version, define
* VERSION_1.5.
*/
package com.ibm.icu.dev.tool.docs;
import com.sun.javadoc.*;
import com.sun.tools.doclets.*;
#ifdef VERSION_1.5
import com.sun.tools.doclets.internal.toolkit.taglets.*;
import com.sun.tools.doclets.internal.toolkit.taglets.Taglet;
// stupid jdk 1.5 contains both com.sun.tools.doclets.Taglet and
// jdk 1.5 contains both com.sun.tools.doclets.Taglet and
// com.sun.tools.doclets.internal.toolkit.taglets.Taglet.
// their registration code casts to the second, not the first, and the
// Their registration code casts to the second, not the first, and the
// second doesn't implement the first, so if you just implement the
// first, you die.
#endif
import java.text.BreakIterator;
import java.util.Locale;
@ -40,7 +50,9 @@ public abstract class ICUTaglet implements Taglet {
ICUInternalTaglet.register(taglets);
ICUDraftTaglet.register(taglets);
ICUStableTaglet.register(taglets);
// ICUDeprecatedTaglet.register(taglets);
#ifndef VERSION_1.5
ICUDeprecatedTaglet.register(taglets);
#endif
ICUObsoleteTaglet.register(taglets);
ICUIgnoreTaglet.register(taglets);
}
@ -100,6 +112,7 @@ public abstract class ICUTaglet implements Taglet {
}
return null;
}
#ifdef VERSION_1.5
public TagletOutput getTagletOutput(Tag tag, TagletWriter writer) throws IllegalArgumentException {
TagletOutput out = writer.getTagletOutputInstance();
@ -116,6 +129,7 @@ public abstract class ICUTaglet implements Taglet {
out.setOutput(toString(tags[0]));
return out;
}
#endif
protected static final String STATUS = "<dt><b>Status:</b></dt>";
@ -175,12 +189,12 @@ public abstract class ICUTaglet implements Taglet {
}
}
}
#ifndef VERSION_1.5
/*
* sigh, in JDK 1.5 we can't override the standard deprecated taglet
* so easily. I'm not impressed with the javadoc code.
*
*/
public static class ICUDeprecatedTaglet extends ICUTaglet {
private static final String NAME = "deprecated";
@ -207,7 +221,7 @@ public abstract class ICUTaglet implements Taglet {
}
}
}
*/
#endif
public static class ICUObsoleteTaglet extends ICUTaglet {
private static final String NAME = "obsolete";