mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-12 00:14:25 +00:00
ICU-4460 make taglet work for both 1.4 and 1.5
X-SVN-Rev: 17391
This commit is contained in:
parent
1ef9ce4649
commit
a67194865d
2 changed files with 239 additions and 6 deletions
219
icu4j/src/com/ibm/icu/dev/tool/docs/CodeMangler.java
Normal file
219
icu4j/src/com/ibm/icu/dev/tool/docs/CodeMangler.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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";
|
Loading…
Add table
Reference in a new issue