Tom Tromey writes:
>> This needs a corresponding gcj.texi patch.
Andrew> Yes, but I'm waiting for feedback before I write it.
I think the idea is sound, and needed.
I think we should also support reading "find -0" output,
i.e. '\0'-separated strings. That would let us support file names
with spaces in them, and other oddities.
2005-04-05 Andrew Haley <aph(a)redhat.com>
* gnu/gcj/tools/gcj_dbtool/Main.java (Fileset): New class.
(Tokenizer): New class.
(getFiles): New method.
(main): Add "-" argument.
Add "-0" argument.
Read list of files from stdin when merging map databases.
(usage): Add "-" argument.
Add "-0" argument.
Minor corrections.
Index: gnu/gcj/tools/gcj_dbtool/Main.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/gcj/tools/gcj_dbtool/Main.java,v
retrieving revision 1.9
diff -p -2 -c -r1.9 Main.java
*** gnu/gcj/tools/gcj_dbtool/Main.java 25 Mar 2005 00:38:43 -0000 1.9
--- gnu/gcj/tools/gcj_dbtool/Main.java 5 Apr 2005 14:10:33 -0000
*************** public class Main
*** 23,27 ****
--- 23,42 ----
public static void main (String[] s)
{
+ boolean fileListFromStdin = false;
+ char filenameSeparator = ' ';
+
insist (s.length >= 1);
+
+ if (s[0].equals("-") ||
+ s[0].equals("-0"))
+ {
+ if (s[0].equals("-0"))
+ filenameSeparator = (char)0;
+ fileListFromStdin = true;
+ String[] newArgs = new String[s.length - 1];
+ System.arraycopy(s, 1, newArgs, 0, s.length - 1);
+ s = newArgs;
+ }
+
if (s[0].equals("-v") || s[0].equals("--version"))
{
*************** public class Main
*** 146,150 ****
{
// Merge databases.
! insist (s.length >= 3);
try
{
--- 161,166 ----
{
// Merge databases.
! insist (s.length >= 3
! || fileListFromStdin && s.length == 2);
try
{
*************** public class Main
*** 156,171 ****
int newSize = 0;
int newStringTableSize = 0;
! PersistentByteMap[] sourceMaps = new PersistentByteMap[s.length - 2];
// Scan all the input files, calculating worst case string
// table and hash table use.
! for (int i = 2; i < s.length; i++)
! {
! PersistentByteMap b
! = new PersistentByteMap(new File(s[i]),
! PersistentByteMap.AccessMode.READ_ONLY);
! newSize += b.size();
! newStringTableSize += b.stringTableSize();
! sourceMaps[i - 2] = b;
! }
newSize *= 1.5; // Scaling the new size by 1.5 results in
--- 172,195 ----
int newSize = 0;
int newStringTableSize = 0;
! Fileset files = getFiles(s, 2, fileListFromStdin,
! filenameSeparator);
! PersistentByteMap[] sourceMaps
! = new PersistentByteMap[files.size()];
!
// Scan all the input files, calculating worst case string
// table and hash table use.
! {
! Iterator it = files.iterator();
! int i = 0;
! while (it.hasNext())
! {
! PersistentByteMap b
! = new PersistentByteMap((File)it.next(),
! PersistentByteMap.AccessMode.READ_ONLY);
! newSize += b.size();
! newStringTableSize += b.stringTableSize();
! sourceMaps[i++] = b;
! }
! }
newSize *= 1.5; // Scaling the new size by 1.5 results in
*************** public class Main
*** 173,177 ****
PersistentByteMap map
= PersistentByteMap.emptyPersistentByteMap
! (temp, newSize, newStringTableSize);
for (int i = 0; i < sourceMaps.length; i++)
--- 197,201 ----
PersistentByteMap map
= PersistentByteMap.emptyPersistentByteMap
! (temp, newSize, newStringTableSize);
for (int i = 0; i < sourceMaps.length; i++)
*************** public class Main
*** 297,310 ****
+ " gcj-dbtool -n file.gcjdb [size] - Create a new gcj map
database\n"
+ " gcj-dbtool -a file.gcjdb file.jar file.so\n"
! + " - Add the contents of file.jar to a new gcj map
database\n"
+ " gcj-dbtool -f file.gcjdb file.jar file.so\n"
! + " - Add the contents of file.jar to a new gcj map
database\n"
+ " gcj-dbtool -t file.gcjdb - Test a gcj map
database\n"
+ " gcj-dbtool -l file.gcjdb - List a gcj map
database\n"
! + " gcj-dbtool -m dest.gcjdb [source.gcjdb]...\n"
! + " - Merge gcj map databases into dest\n"
! + " Replaces dest\n"
! + " To add to dest, include dest in the list of
sources\n"
! + " gcj-dbtool -p [LIBDIR] - Print default database
name");
}
--- 321,337 ----
+ " gcj-dbtool -n file.gcjdb [size] - Create a new gcj map
database\n"
+ " gcj-dbtool -a file.gcjdb file.jar file.so\n"
! + " - Add the contents of file.jar to a gcj map database\n"
+ " gcj-dbtool -f file.gcjdb file.jar file.so\n"
! + " - Add the contents of file.jar to a gcj map database\n"
+ " gcj-dbtool -t file.gcjdb - Test a gcj map
database\n"
+ " gcj-dbtool -l file.gcjdb - List a gcj map
database\n"
! + " gcj-dbtool [-][-0] -m dest.gcjdb [source.gcjdb]...\n"
! + " - Merge gcj map databases into dest\n"
! + " Replaces dest\n"
! + " To add to dest, include dest in the list of
sources\n"
! + " If the first arg is -, read the list from stdin\n"
! + " If the first arg is -0, filenames separated by nul\n"
! + " gcj-dbtool -p [LIBDIR] - Print default database
name"
! );
}
*************** public class Main
*** 406,409 ****
return hexBytes.toString();
}
}
-
--- 433,535 ----
return hexBytes.toString();
}
+
+
+ // Return a Fileset, either from a String array or from System.in,
+ // depending on fileListFromStdin.
+ private static final Fileset getFiles(String[] s, int startPos,
+ boolean fileListFromStdin,
+ char separator)
+ {
+ if (fileListFromStdin)
+ return new Fileset(System.in, separator);
+ else
+ return new Fileset(s, startPos, s.length);
+ }
+ }
+
+ // Parse a stream into tokens. The separator can be any char, and
+ // space is equivalent to any whitepace character.
+ class Tokenizer
+ {
+ final Reader r;
+ final char separator;
+
+ Tokenizer(Reader r, char separator)
+ {
+ this.r = r;
+ this.separator = separator;
+ }
+
+ boolean isSeparator(int c)
+ {
+ if (Character.isWhitespace(separator))
+ return Character.isWhitespace((char)c);
+ else
+ return c == separator;
+ }
+
+ // Parse a token from the input stream. Return the empty string
+ // when the stream is exhausted.
+ String nextToken ()
+ {
+ StringBuffer buf = new StringBuffer();
+ int c;
+ try
+ {
+ while ((c = r.read()) != -1)
+ {
+ if (! isSeparator(c))
+ {
+ buf.append((char)c);
+ break;
+ }
+ }
+ while ((c = r.read()) != -1)
+ {
+ if (isSeparator(c))
+ break;
+ else
+ buf.append((char)c);
+ }
+ }
+ catch (java.io.IOException e)
+ {
+ }
+ return buf.toString();
+ }
+ }
+
+ // A Fileset is a container for a set of files; it can be created
+ // either from a string array or from an input stream, given a
+ // separator character.
+ class Fileset
+ {
+ LinkedHashSet files = new LinkedHashSet();
+
+ Fileset (String[] s, int start, int end)
+ {
+ for (int i = start; i < end; i++)
+ {
+ files.add(new File(s[i]));
+ }
+ }
+
+ Fileset (InputStream is, char separator)
+ {
+ Reader r = new BufferedReader(new InputStreamReader(is));
+ Tokenizer st = new Tokenizer(r, separator);
+ String name;
+ while (! "".equals(name = st.nextToken()))
+ files.add(new File(name));
+ }
+
+ Iterator iterator()
+ {
+ return files.iterator();
+ }
+
+ int size()
+ {
+ return files.size();
+ }
}