It's been pointed out to me that if we merge db's with the obvious (find . -name 'temp-*.db' | xargs gcj-dbtool -m $DB) we run the risk of failure if arg length exceeds the operating system limit, because xargs will call gcj-dbtool several times. The right way to fix this is to have gcj-dbtool read a list of files from stdin, which is what this patch does. (find . -name 'temp-*.db' | gcj-dbtool - -m $DB) Andrew. 2005-03-30 Andrew Haley <aph@xxxxxxxxxx> * gnu/gcj/tools/gcj_dbtool/Main.java (Fileset): New class. (getFiles): New method. (main): Add "-" argument. Read list of files from stdin when merging map databases. (usage): Add "-" argument. Minor corrections. Index: Main.java =================================================================== RCS file: /cvs/gcc/gcc/libjava/gnu/gcj/tools/gcj_dbtool/Main.java,v retrieving revision 1.9 diff -c -2 -p -r1.9 Main.java *** Main.java 25 Mar 2005 00:38:43 -0000 1.9 --- Main.java 30 Mar 2005 15:04:15 -0000 *************** public class Main *** 23,27 **** --- 23,37 ---- public static void main (String[] s) { + boolean fileListFromStdin = false; insist (s.length >= 1); + + if (s[0].equals("-")) + { + 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,151 **** { // Merge databases. ! insist (s.length >= 3); ! try { File database = new File(s[1]); --- 156,162 ---- { // Merge databases. ! insist (s.length >= 3 ! || fileListFromStdin && s.length == 2); ! try { File database = new File(s[1]); *************** 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 --- 167,188 ---- int newSize = 0; int newStringTableSize = 0; ! Fileset files = getFiles(s, 2, fileListFromStdin); ! 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 *** 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"); } --- 314,329 ---- + " 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 [-] -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" ! + " gcj-dbtool -p [LIBDIR] - Print default database name" ! ); } *************** public class Main *** 406,409 **** --- 425,485 ---- 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) + { + if (fileListFromStdin) + return new Fileset(System.in); + else + return new Fileset(s, startPos, s.length); + } } + // A Fileset is a container for a set of files; it can be created + // either from a string array or from an input stream. + 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) + { + Reader r = new BufferedReader(new InputStreamReader(is)); + StringBuffer buf = new StringBuffer(); + try + { + int chr; + while ((chr = r.read()) != -1) + buf.append((char)chr); + } + catch (IOException _) + { + } + StringTokenizer st = new StringTokenizer(buf.toString()); + while (st.hasMoreElements ()) + { + String name = st.nextToken (); + files.add(new File(name)); + } + } + + Iterator iterator() + { + return files.iterator(); + } + + int size() + { + return files.size(); + } + }