--- a/src/utils/readfile.cpp
+++ b/src/utils/readfile.cpp
@@ -40,27 +40,53 @@
 
 static void caterrno(string *reason, const char *what)
 {
-#define ERRBUFSZ 200    
-    char errbuf[ERRBUFSZ];
     if (reason) {
-	*reason += "file_to_string: ";
-	*reason += what;
-	*reason += ": ";
+	reason->append("file_to_string: ");
+	reason->append(what);
+	reason->append(": ");
 #ifdef sun
 	// Note: sun strerror is noted mt-safe ??
-	*reason += strerror(errno);
+	reason->append(strerror(errno));
 #else
+#define ERRBUFSZ 200    
+	char errbuf[ERRBUFSZ];
 	strerror_r(errno, errbuf, ERRBUFSZ);
-	*reason += errbuf;
+	reason->append(errbuf);
 #endif
     }
 }
 
-// Note: the fstat() + reserve() calls divide cpu usage almost by 2
+class FileToString : public FileScanDo {
+public:
+    FileToString(string& data) : m_data(data) {}
+    string& m_data;
+    bool init(unsigned int size, string *reason) {
+	if (size > 0)
+	    m_data.reserve(size); 
+	return true;
+    }
+    bool data(const char *buf, int cnt, string *reason) {
+	try {
+	    m_data.append(buf, cnt);
+	} catch (...) {
+	    caterrno(reason, "append");
+	    return false;
+	}
+	return true;
+    }
+};
+
+bool file_to_string(const string &fn, string &data, string *reason)
+{
+    FileToString accum(data);
+    return file_scan(fn, &accum, reason);
+}
+
+// Note: the fstat() + reserve() (in init()) calls divide cpu usage almost by 2
 // on both linux i586 and macosx (compared to just append())
 // Also tried a version with mmap, but it's actually slower on the mac and not
 // faster on linux.
-bool file_to_string(const string &fn, string &data, string *reason)
+bool file_scan(const string &fn, FileScanDo* doer, string *reason)
 {
     bool ret = false;
     bool noclosing = true;
@@ -72,19 +98,16 @@
     // If we have a file name, open it, else use stdin.
     if (!fn.empty()) {
 	fd = open(fn.c_str(), O_RDONLY|O_STREAMING);
-	if (fd < 0 
-#if 1
-	    || fstat(fd, &st) < 0
-#endif
-	    ) {
+	if (fd < 0 || fstat(fd, &st) < 0) {
 	    caterrno(reason, "open/stat");
 	    return false;
 	}
 	noclosing = false;
     }
     if (st.st_size > 0)
-	data.reserve(st.st_size+1);
-
+	doer->init(st.st_size+1, reason);
+    else 
+	doer->init(0, reason);
     char buf[4096];
     for (;;) {
 	int n = read(fd, buf, 4096);
@@ -95,10 +118,7 @@
 	if (n == 0)
 	    break;
 
-	try {
-	    data.append(buf, n);
-	} catch (...) {
-	    caterrno(reason, "append");
+	if (!doer->data(buf, n, reason)) {
 	    goto out;
 	}
     }
@@ -206,7 +226,7 @@
   } else if (S_ISREG(st.st_mode)) {
       string s, reason;
       if (!file_to_string(top, s, &reason)) {
-	  cerr << reason;
+	  cerr << reason << endl;
 	  exit(1);
       } else {
 	  cout << s;