Пример #1
0
 public String toString(Tag[] tags) {
   if (members == null) members = System.getProperty("battlecode.doc.members").split("\n");
   String[] member;
   if (n < members.length) member = members[n++].split("\\.");
   else return null;
   if ("RobotType".equals(member[0])) return toString(member[1]);
   else return null;
 }
  public static void main(String[] args) {
    String thisFile =
        "" + new java.io.File(System.getProperty("test.src", "."), "BreakIteratorWarning.java");

    if (com.sun.tools.javadoc.Main.execute(
            "javadoc",
            "BreakIteratorWarning",
            BreakIteratorWarning.class.getClassLoader(),
            new String[] {"-Xwerror", thisFile})
        != 0) throw new Error("Javadoc encountered warnings or errors.");
  }
Пример #3
0
  // Entry point
  public static void main(String[] args) {

    // Directory that contains source files that javadoc runs on
    String srcdir = System.getProperty("test.src", ".");

    // Test for all cases except the split index page
    runJavadoc(
        new String[] {
          "-d", TMPDEST_DIR1,
          "-sourcepath", srcdir,
          "p1", "p2"
        });
    runTestsOnHTML(testArray);

    printSummary();
  }
Пример #4
0
/**
 * Runs javadoc and runs regression tests on the resulting HTML. It reads each file, complete with
 * newlines, into a string to easily find strings that contain newlines.
 */
public class AccessFrameTitle {

  private static final String BUGID = "4636655";
  private static final String BUGNAME = "AccessFrameTitle";
  private static final String FS = System.getProperty("file.separator");
  private static final String PS = System.getProperty("path.separator");
  private static final String TMPDEST_DIR1 = "." + FS + "docs1" + FS;
  private static final String TMPDEST_DIR2 = "." + FS + "docs2" + FS;

  // Subtest number.  Needed because runResultsOnHTML is run twice,
  // and subtestNum should increment across subtest runs.
  public static int subtestNum = 0;
  public static int numSubtestsPassed = 0;

  // Entry point
  public static void main(String[] args) {

    // Directory that contains source files that javadoc runs on
    String srcdir = System.getProperty("test.src", ".");

    // Test for all cases except the split index page
    runJavadoc(
        new String[] {
          "-d", TMPDEST_DIR1,
          "-sourcepath", srcdir,
          "p1", "p2"
        });
    runTestsOnHTML(testArray);

    printSummary();
  }

  /** Run javadoc */
  public static void runJavadoc(String[] javadocArgs) {
    if (com.sun.tools.javadoc.Main.execute(javadocArgs) != 0) {
      throw new Error("Javadoc failed to execute");
    }
  }

  /**
   * Assign value for [ stringToFind, filename ] NOTE: The standard doclet uses the same separator
   * "\n" for all OS's
   */
  private static final String[][] testArray = {

    // Testing only for the presence of the title attributes.
    // To make this test more robust, only
    // the initial part of each title string is tested for,
    // in case the ending part of the string later changes

    {
      "title=\"All classes and interfaces (except non-static nested types)\"",
      TMPDEST_DIR1 + "index.html"
    },
    {"title=\"All Packages\"", TMPDEST_DIR1 + "index.html"},
    {"title=\"Package, class and interface descriptions\"", TMPDEST_DIR1 + "index.html"},
  };

  public static void runTestsOnHTML(String[][] testArray) {

    for (int i = 0; i < testArray.length; i++) {

      subtestNum += 1;

      // Read contents of file into a string
      String fileString = readFileToString(testArray[i][1]);

      // Get string to find
      String stringToFind = testArray[i][0];

      // Find string in file's contents
      if (findString(fileString, stringToFind) == -1) {
        System.out.println(
            "\nSub-test "
                + (subtestNum)
                + " for bug "
                + BUGID
                + " ("
                + BUGNAME
                + ") FAILED\n"
                + "when searching for:\n"
                + stringToFind);
      } else {
        numSubtestsPassed += 1;
        System.out.println("\nSub-test " + (subtestNum) + " passed:\n" + stringToFind);
      }
    }
  }

  public static void printSummary() {
    if (numSubtestsPassed == subtestNum) {
      System.out.println("\nAll " + numSubtestsPassed + " subtests passed");
    } else {
      throw new Error(
          "\n"
              + (subtestNum - numSubtestsPassed)
              + " of "
              + (subtestNum)
              + " subtests failed for bug "
              + BUGID
              + " ("
              + BUGNAME
              + ")\n");
    }
  }

  // Read the file into a String
  public static String readFileToString(String filename) {
    try {
      File file = new File(filename);
      if (!file.exists()) {
        System.out.println("\nFILE DOES NOT EXIST: " + filename);
      }
      BufferedReader in = new BufferedReader(new FileReader(file));

      // Create an array of characters the size of the file
      char[] allChars = new char[(int) file.length()];

      // Read the characters into the allChars array
      in.read(allChars, 0, (int) file.length());
      in.close();

      // Convert to a string
      String allCharsString = new String(allChars);

      return allCharsString;

    } catch (FileNotFoundException e) {
      System.err.println(e);
      return "";
    } catch (IOException e) {
      System.err.println(e);
      return "";
    }
  }

  public static int findString(String fileString, String stringToFind) {
    return fileString.indexOf(stringToFind);
  }
}
Пример #5
0
/*
 * @author  Sucheta Dambalkar(Revised)
 */
public class LLNI extends Gen {

  protected final char pathChar = File.separatorChar;
  protected final char innerDelim = '$'; /* For inner classes */
  protected Hashtable doneHandleTypes;
  MemberDoc[] fields;
  MemberDoc[] methods;
  private boolean doubleAlign;
  private int padFieldNum = 0;

  LLNI(boolean doubleAlign, RootDoc root) {
    super(root);
    this.doubleAlign = doubleAlign;
  }

  protected String getIncludes() {
    return "";
  }

  protected void write(OutputStream o, ClassDoc clazz) throws ClassNotFoundException {
    String cname = mangleClassName(clazz.qualifiedName());
    PrintWriter pw = wrapWriter(o);
    fields = clazz.fields();
    methods = clazz.methods();
    generateDeclsForClass(pw, clazz, cname);
  }

  protected void generateDeclsForClass(PrintWriter pw, ClassDoc clazz, String cname)
      throws ClassNotFoundException {
    doneHandleTypes = new Hashtable();
    /* The following handle types are predefined in "typedefs.h". Suppress
    inclusion in the output by generating them "into the blue" here. */
    genHandleType(null, "java.lang.Class");
    genHandleType(null, "java.lang.ClassLoader");
    genHandleType(null, "java.lang.Object");
    genHandleType(null, "java.lang.String");
    genHandleType(null, "java.lang.Thread");
    genHandleType(null, "java.lang.ThreadGroup");
    genHandleType(null, "java.lang.Throwable");

    pw.println("/* LLNI Header for class " + clazz.qualifiedName() + " */" + lineSep);
    pw.println("#ifndef _Included_" + cname);
    pw.println("#define _Included_" + cname);
    pw.println("#include \"typedefs.h\"");
    pw.println("#include \"llni.h\"");
    pw.println("#include \"jni.h\"" + lineSep);

    forwardDecls(pw, clazz);
    structSectionForClass(pw, clazz, cname);
    methodSectionForClass(pw, clazz, cname);
    pw.println("#endif");
  }

  protected void genHandleType(PrintWriter pw, String clazzname) {
    String cname = mangleClassName(clazzname);
    if (!doneHandleTypes.containsKey(cname)) {
      doneHandleTypes.put(cname, cname);
      if (pw != null) {
        pw.println("#ifndef DEFINED_" + cname);
        pw.println("    #define DEFINED_" + cname);
        pw.println("    GEN_HANDLE_TYPES(" + cname + ");");
        pw.println("#endif" + lineSep);
      }
    }
  }

  protected String mangleClassName(String s) {
    return s.replace('.', '_').replace(pathChar, '_').replace(innerDelim, '_');
  }

  protected void forwardDecls(PrintWriter pw, ClassDoc clazz) throws ClassNotFoundException {
    ClassDoc clazzfield = null;

    if (clazz.qualifiedName().equals("java.lang.Object")) return;
    genHandleType(pw, clazz.qualifiedName());
    ClassDoc superClass = clazz.superclass();

    if (superClass != null) {
      String superClassName = superClass.qualifiedName();
      forwardDecls(pw, superClass);
    }

    for (int i = 0; i < fields.length; i++) {
      FieldDoc field = (FieldDoc) fields[i];

      if (!field.isStatic()) {
        Type t = field.type();
        String tname = t.qualifiedTypeName();
        TypeSignature newTypeSig = new TypeSignature(root);
        String sig = newTypeSig.getTypeSignature(tname);

        if (sig.charAt(0) != '[') forwardDeclsFromSig(pw, sig);
      }
    }

    for (int i = 0; i < methods.length; i++) {
      MethodDoc method = (MethodDoc) methods[i];

      if (method.isNative()) {
        Type retType = method.returnType();
        String typesig = method.signature();
        TypeSignature newTypeSig = new TypeSignature(root);
        String sig = newTypeSig.getTypeSignature(typesig, retType);

        if (sig.charAt(0) != '[') forwardDeclsFromSig(pw, sig);
      }
    }
  }

  protected void forwardDeclsFromSig(PrintWriter pw, String sig) {
    int len = sig.length();
    int i = sig.charAt(0) == '(' ? 1 : 0;

    /* Skip the initial "(". */
    while (i < len) {
      if (sig.charAt(i) == 'L') {
        int j = i + 1;
        while (sig.charAt(j) != ';') j++;
        genHandleType(pw, sig.substring(i + 1, j));
        i = j + 1;
      } else {
        i++;
      }
    }
  }

  protected void structSectionForClass(PrintWriter pw, ClassDoc jclazz, String cname)
      throws ClassNotFoundException {

    String jname = jclazz.qualifiedName();

    if (cname.equals("java_lang_Object")) {
      pw.println("/* struct java_lang_Object is defined in typedefs.h. */");
      pw.println();
      return;
    }
    pw.println("#if !defined(__i386)");
    pw.println("#pragma pack(4)");
    pw.println("#endif");
    pw.println();
    pw.println("struct " + cname + " {");
    pw.println("    ObjHeader h;");
    pw.print(fieldDefs(jclazz, cname));

    if (jname.equals("java.lang.Class"))
      pw.println("    Class *LLNI_mask(cClass);" + "  /* Fake field; don't access (see oobj.h) */");
    pw.println("};" + lineSep + lineSep + "#pragma pack()");
    pw.println();
    return;
  }

  private static class FieldDefsRes {
    public String className; /* Name of the current class. */
    public FieldDefsRes parent;
    public String s;
    public int byteSize;
    public boolean bottomMost;
    public boolean printedOne = false;

    FieldDefsRes(ClassDoc clazz, FieldDefsRes parent, boolean bottomMost) {
      this.className = clazz.qualifiedName();
      this.parent = parent;
      this.bottomMost = bottomMost;
      int byteSize = 0;
      if (parent == null) this.s = "";
      else this.s = parent.s;
    }
  }

  /* Returns "true" iff added a field. */
  private boolean doField(FieldDefsRes res, FieldDoc field, String cname, boolean padWord)
      throws ClassNotFoundException {

    String fieldDef = addStructMember(field, cname, padWord);
    if (fieldDef != null) {
      if (!res.printedOne) {
        /* add separator */
        if (res.bottomMost) {
          if (res.s.length() != 0) res.s = res.s + "    /* local members: */" + lineSep;
        } else {
          res.s = res.s + "    /* inherited members from " + res.className + ": */" + lineSep;
        }
        res.printedOne = true;
      }
      res.s = res.s + fieldDef;
      return true;
    }

    // Otherwise.
    return false;
  }

  private int doTwoWordFields(
      FieldDefsRes res, ClassDoc clazz, int offset, String cname, boolean padWord)
      throws ClassNotFoundException {
    boolean first = true;
    FieldDoc[] fields = clazz.fields();

    for (int i = 0; i < fields.length; i++) {
      FieldDoc field = fields[i];
      String tc = field.type().typeName();
      boolean twoWords = (tc.equals("long") || tc.equals("double"));
      if (twoWords && doField(res, field, cname, first && padWord)) {
        offset += 8;
        first = false;
      }
    }
    return offset;
  }

  protected String fieldDefs(ClassDoc clazz, String cname) throws ClassNotFoundException {
    FieldDefsRes res = fieldDefs(clazz, cname, true);
    return res.s;
  }

  protected FieldDefsRes fieldDefs(ClassDoc clazz, String cname, boolean bottomMost)
      throws ClassNotFoundException {
    FieldDefsRes res;
    int offset;
    boolean didTwoWordFields = false;
    ClassDoc superclazz = clazz.superclass();

    if (superclazz != null) {
      String supername = superclazz.qualifiedName();
      res = new FieldDefsRes(clazz, fieldDefs(superclazz, cname, false), bottomMost);
      offset = res.parent.byteSize;
    } else {
      res = new FieldDefsRes(clazz, null, bottomMost);
      offset = 0;
    }

    FieldDoc[] fields = clazz.fields();

    for (int i = 0; i < fields.length; i++) {
      FieldDoc field = fields[i];

      if (doubleAlign && !didTwoWordFields && (offset % 8) == 0) {
        offset = doTwoWordFields(res, clazz, offset, cname, false);
        didTwoWordFields = true;
      }

      String tc = field.type().typeName();
      boolean twoWords = (tc.equals("long") || tc.equals("double"));

      if (!doubleAlign || !twoWords) {
        if (doField(res, field, cname, false)) offset += 4;
      }
    }

    if (doubleAlign && !didTwoWordFields) {
      if ((offset % 8) != 0) offset += 4;
      offset = doTwoWordFields(res, clazz, offset, cname, true);
    }

    res.byteSize = offset;
    return res;
  }

  /* OVERRIDE: This method handles instance fields */
  protected String addStructMember(FieldDoc member, String cname, boolean padWord)
      throws ClassNotFoundException {
    String res = null;

    if (member.isStatic()) {
      res = addStaticStructMember(member, cname);
      //   if (res == null) /* JNI didn't handle it, print comment. */
      //  res = "    /* Inaccessible static: " + member + " */" + lineSep;
    } else {
      if (padWord) res = "    java_int padWord" + padFieldNum++ + ";" + lineSep;
      res = "    " + llniType(member.type(), false, false) + " " + llniFieldName(member);
      if (isLongOrDouble(member.type())) res = res + "[2]";
      res = res + ";" + lineSep;
    }
    return res;
  }

  private static final boolean isWindows = System.getProperty("os.name").startsWith("Windows");

  /*
   * This method only handles static final fields.
   */
  protected String addStaticStructMember(FieldDoc field, String cname)
      throws ClassNotFoundException {
    String res = null;
    Object exp = null;

    if (!field.isStatic()) return res;
    if (!field.isFinal()) return res;

    exp = field.constantValue();

    if (exp != null) {
      /* Constant. */

      String cn = cname + "_" + field.name();
      String suffix = null;
      long val = 0;
      /* Can only handle int, long, float, and double fields. */
      if (exp instanceof Integer) {
        suffix = "L";
        val = ((Integer) exp).intValue();
      }
      if (exp instanceof Long) {
        // Visual C++ supports the i64 suffix, not LL
        suffix = isWindows ? "i64" : "LL";
        val = ((Long) exp).longValue();
      }
      if (exp instanceof Float) suffix = "f";
      if (exp instanceof Double) suffix = "";
      if (suffix != null) {
        // Some compilers will generate a spurious warning
        // for the integer constants for Integer.MIN_VALUE
        // and Long.MIN_VALUE so we handle them specially.
        if ((suffix.equals("L") && (val == Integer.MIN_VALUE))
            || (suffix.equals("LL") && (val == Long.MIN_VALUE))) {
          res =
              "    #undef  "
                  + cn
                  + lineSep
                  + "    #define "
                  + cn
                  + " ("
                  + (val + 1)
                  + suffix
                  + "-1)"
                  + lineSep;
        } else {
          res =
              "    #undef  "
                  + cn
                  + lineSep
                  + "    #define "
                  + cn
                  + " "
                  + exp.toString()
                  + suffix
                  + lineSep;
        }
      }
    }
    return res;
  }

  protected void methodSectionForClass(PrintWriter pw, ClassDoc clazz, String cname)
      throws ClassNotFoundException {
    String methods = methodDecls(clazz, cname);

    if (methods.length() != 0) {
      pw.println("/* Native method declarations: */" + lineSep);
      pw.println("#ifdef __cplusplus");
      pw.println("extern \"C\" {");
      pw.println("#endif" + lineSep);
      pw.println(methods);
      pw.println("#ifdef __cplusplus");
      pw.println("}");
      pw.println("#endif");
    }
  }

  protected String methodDecls(ClassDoc clazz, String cname) throws ClassNotFoundException {

    String res = "";
    for (int i = 0; i < methods.length; i++) {
      MethodDoc method = (MethodDoc) methods[i];
      if (method.isNative()) res = res + methodDecl(method, clazz, cname);
    }
    return res;
  }

  protected String methodDecl(MethodDoc method, ClassDoc clazz, String cname)
      throws ClassNotFoundException {
    String res = null;

    Type retType = method.returnType();
    String typesig = method.signature();
    TypeSignature newTypeSig = new TypeSignature(root);
    String sig = newTypeSig.getTypeSignature(typesig, retType);
    boolean longName = needLongName(method, clazz);

    if (sig.charAt(0) != '(') Util.error("invalid.method.signature", sig);

    res =
        "JNIEXPORT "
            + jniType(retType)
            + " JNICALL"
            + lineSep
            + jniMethodName(method, cname, longName)
            + "(JNIEnv *, "
            + cRcvrDecl(method, cname);
    Parameter[] params = method.parameters();
    Type argTypes[] = new Type[params.length];
    for (int p = 0; p < params.length; p++) {
      argTypes[p] = params[p].type();
    }

    /* It would have been nice to include the argument names in the
    declaration, but there seems to be a bug in the "BinaryField"
    class, causing the getArguments() method to return "null" for
    most (non-constructor) methods. */
    for (int i = 0; i < argTypes.length; i++) res = res + ", " + jniType(argTypes[i]);
    res = res + ");" + lineSep;
    return res;
  }

  protected final boolean needLongName(MethodDoc method, ClassDoc clazz)
      throws ClassNotFoundException {
    String methodName = method.name();
    for (int i = 0; i < methods.length; i++) {
      MethodDoc memberMethod = (MethodDoc) methods[i];
      if ((memberMethod != method)
          && memberMethod.isNative()
          && (methodName == memberMethod.name())) return true;
    }
    return false;
  }

  protected final String jniMethodName(MethodDoc method, String cname, boolean longName) {
    String res = "Java_" + cname + "_" + method.name();

    if (longName) {
      Type mType = method.returnType();
      Parameter[] params = method.parameters();
      Type argTypes[] = new Type[params.length];
      for (int p = 0; p < params.length; p++) {
        argTypes[p] = params[p].type();
      }

      res = res + "__";
      for (int i = 0; i < argTypes.length; i++) {
        Type t = argTypes[i];
        String tname = t.typeName();
        TypeSignature newTypeSig = new TypeSignature(root);
        String sig = newTypeSig.getTypeSignature(tname);
        res = res + nameToIdentifier(sig);
      }
    }
    return res;
  }

  protected final String jniType(Type t) {
    String elmT = t.typeName();
    if (t.dimension().indexOf("[]") != -1) {
      if (elmT.equals("boolean")) return "jbooleanArray";
      else if (elmT.equals("byte")) return "jbyteArray";
      else if (elmT.equals("char")) return "jcharArray";
      else if (elmT.equals("short")) return "jshortArray";
      else if (elmT.equals("int")) return "jintArray";
      else if (elmT.equals("long")) return "jlongArray";
      else if (elmT.equals("float")) return "jfloatArray";
      else if (elmT.equals("double")) return "jdoubleArray";
      else if ((t.dimension().indexOf("[][]") != -1) || (t.asClassDoc() != null))
        return "jobjectArray";
    } else {
      if (elmT.equals("void")) return "void";
      else if (elmT.equals("boolean")) return "jboolean";
      else if (elmT.equals("byte")) return "jbyte";
      else if (elmT.equals("char")) return "jchar";
      else if (elmT.equals("short")) return "jshort";
      else if (elmT.equals("int")) return "jint";
      else if (elmT.equals("long")) return "jlong";
      else if (elmT.equals("float")) return "jfloat";
      else if (elmT.equals("double")) return "jdouble";
      else if (t.asClassDoc() != null) {
        if (elmT.equals("String")) return "jstring";
        else if (t.asClassDoc().subclassOf(root.classNamed("java.lang.Class"))) return "jclass";
        else return "jobject";
      }
    }
    Util.bug("jni.unknown.type");
    return null; /* dead code. */
  }

  protected String llniType(Type t, boolean handleize, boolean longDoubleOK) {
    String res = null;
    String elmt = t.typeName();
    if (t.dimension().indexOf("[]") != -1) {
      if ((t.dimension().indexOf("[][]") != -1) || (t.asClassDoc() != null)) res = "IArrayOfRef";
      else if (elmt.equals("boolean")) res = "IArrayOfBoolean";
      else if (elmt.equals("byte")) res = "IArrayOfByte";
      else if (elmt.equals("char")) res = "IArrayOfChar";
      else if (elmt.equals("int")) res = "IArrayOfInt";
      else if (elmt.equals("long")) res = "IArrayOfLong";
      else if (elmt.equals("float")) res = "IArrayOfFloat";
      else if (elmt.equals("double")) res = "IArrayOfDouble";
      if (!handleize) res = "DEREFERENCED_" + res;
    } else {
      if (elmt.equals("void")) res = "void";
      else if ((elmt.equals("boolean"))
          || (elmt.equals("byte"))
          || (elmt.equals("char"))
          || (elmt.equals("short"))
          || (elmt.equals("int"))) res = "java_int";
      else if (elmt.equals("long")) res = longDoubleOK ? "java_long" : "val32 /* java_long */";
      else if (elmt.equals("float")) res = "java_float";
      else if (elmt.equals("double"))
        res = res = longDoubleOK ? "java_double" : "val32 /* java_double */";
      else if (t.asClassDoc() != null) {
        res = "I" + mangleClassName(t.asClassDoc().qualifiedName());
        if (!handleize) res = "DEREFERENCED_" + res;
      }
    }
    return res;
  }

  protected final String cRcvrDecl(MemberDoc field, String cname) {
    return (field.isStatic() ? "jclass" : "jobject");
  }

  protected String maskName(String s) {
    return "LLNI_mask(" + s + ")";
  }

  protected String llniFieldName(MemberDoc field) {
    return maskName(field.name());
  }

  protected final boolean isLongOrDouble(Type t) {
    String tc = t.typeName();
    return (tc.equals("long") || tc.equals("double"));
  }

  /* Do unicode to ansi C identifier conversion.
  %%% This may not be right, but should be called more often. */
  protected final String nameToIdentifier(String name) {
    int len = name.length();
    StringBuffer buf = new StringBuffer(len);
    for (int i = 0; i < len; i++) {
      char c = name.charAt(i);
      if (isASCIILetterOrDigit(c)) buf.append(c);
      else if (c == '/') buf.append('_');
      else if (c == '.') buf.append('_');
      else if (c == '_') buf.append("_1");
      else if (c == ';') buf.append("_2");
      else if (c == '[') buf.append("_3");
      else buf.append("_0" + ((int) c));
    }
    return new String(buf);
  }

  protected final boolean isASCIILetterOrDigit(char c) {
    if (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')) || ((c >= '0') && (c <= '9')))
      return true;
    else return false;
  }
}
Пример #6
0
 /**
  * Add at least the first sentence from a doc block for a package to the API. This is used by the
  * report generator if no comment is provided. The default source tree may not include the
  * package.html files, so this may be unavailable in many cases. Need to make sure that HTML tags
  * are not confused with XML tags. This could be done by stuffing the &lt; character to another
  * string or by handling HTML in the parser. This second option is neater. Note that XML expects
  * all element tags to have either a closing "/>" or a matching end element tag. Due to the
  * difficulties of converting incorrect HTML to XHTML, the first option is used.
  */
 public void addPkgDocumentation(RootDoc root, PackageDoc pd, int indent) {
   String rct = null;
   String filename = pd.name();
   try {
     // See if the source path was specified as part of the
     // options and prepend it if it was.
     String srcLocation = null;
     String[][] options = root.options();
     for (int opt = 0; opt < options.length; opt++) {
       if ((options[opt][0]).compareTo("-sourcepath") == 0) {
         srcLocation = options[opt][1];
         break;
       }
     }
     filename = filename.replace('.', JDiff.DIR_SEP.charAt(0));
     if (srcLocation != null) {
       // Make a relative location absolute
       if (srcLocation.startsWith("..")) {
         String curDir = System.getProperty("user.dir");
         while (srcLocation.startsWith("..")) {
           srcLocation = srcLocation.substring(3);
           int idx = curDir.lastIndexOf(JDiff.DIR_SEP);
           curDir = curDir.substring(0, idx + 1);
         }
         srcLocation = curDir + srcLocation;
       }
       filename = srcLocation + JDiff.DIR_SEP + filename;
     }
     // Try both ".htm" and ".html"
     filename += JDiff.DIR_SEP + "package.htm";
     File f2 = new File(filename);
     if (!f2.exists()) {
       filename += "l";
     }
     FileInputStream f = new FileInputStream(filename);
     BufferedReader d = new BufferedReader(new InputStreamReader(f));
     String str = d.readLine();
     // Ignore everything except the lines between <body> elements
     boolean inBody = false;
     while (str != null) {
       if (!inBody) {
         if (str.toLowerCase().trim().startsWith("<body")) {
           inBody = true;
         }
         str = d.readLine(); // Get the next line
         continue; // Ignore the line
       } else {
         if (str.toLowerCase().trim().startsWith("</body")) {
           inBody = false;
           continue; // Ignore the line
         }
       }
       if (rct == null) rct = str + "\n";
       else rct += str + "\n";
       str = d.readLine();
     }
   } catch (java.io.FileNotFoundException e) {
     // If it doesn't exist, that's fine
     if (trace) System.out.println("No package level documentation file at '" + filename + "'");
   } catch (java.io.IOException e) {
     System.out.println("Error reading file \"" + filename + "\": " + e.getMessage());
     System.exit(5);
   }
   if (rct != null) {
     rct = stripNonPrintingChars(rct, (Doc) pd);
     rct = rct.trim();
     if (rct.compareTo("") != 0
         && rct.indexOf(Comments.placeHolderText) == -1
         && rct.indexOf("InsertOtherCommentsHere") == -1) {
       int idx = endOfFirstSentence(rct);
       if (idx == 0) return;
       for (int i = 0; i < indent; i++) outputFile.print(" ");
       outputFile.println("<doc>");
       for (int i = 0; i < indent; i++) outputFile.print(" ");
       String firstSentence = null;
       if (idx == -1) firstSentence = rct;
       else firstSentence = rct.substring(0, idx + 1);
       String firstSentenceNoTags = API.stuffHTMLTags(firstSentence);
       outputFile.println(firstSentenceNoTags);
       for (int i = 0; i < indent; i++) outputFile.print(" ");
       outputFile.println("</doc>");
     }
   }
 }