00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <sys/types.h>
00025 #include <sys/stat.h>
00026
00027 #include <Basics.H>
00028 #include <FS.H>
00029 #include <Generics.H>
00030 #include <SourceOrDerived.H>
00031
00032 #include "HexReader.H"
00033
00034 using std::ostream;
00035 using std::cout;
00036 using std::cerr;
00037 using std::endl;
00038
00039 static void Syntax(char *msg, char *arg = NULL) throw ()
00040 {
00041 cerr << "Error: " << msg;
00042 if (arg != NULL) cerr << ": '" << arg << "'";
00043 cerr << endl;
00044 cerr << "Syntax: CountShortIds file ..." << endl;
00045 exit(1);
00046 }
00047
00048 static char *FileName(char *name) throw ()
00049 {
00050 char *res = name;
00051 if (strncmp(name, "0x", 2) == 0) {
00052
00053 char *arg = name + 2;
00054
00055
00056 ShortId sid;
00057 if (sscanf(arg, "%x", &sid) != 1) {
00058 Syntax("bad 'shortId' argument", name);
00059 }
00060
00061
00062 res = SourceOrDerived::shortIdToName(sid, false);
00063 }
00064 return res;
00065 }
00066
00067 static Text FormattedSz(double sz) throw ()
00068 {
00069 const double OneK = 1024.0;
00070 char buff[20];
00071 if (sz < OneK) {
00072 sprintf(buff, "%.1f", sz);
00073 } else {
00074 sz /= OneK;
00075 char suffix = 'K';
00076 if (sz >= OneK) {
00077 sz /= OneK;
00078 suffix = 'M';
00079 }
00080 sprintf(buff, "%.1f%c", sz, suffix);
00081 }
00082 return Text(buff);
00083 }
00084
00085 static void Process(ostream &os, char *path, bool warn)
00086 throw (FS::Failure, FS::DoesNotExist)
00087 {
00088
00089 os << path << ":" << endl;
00090
00091
00092 HexReader hexrd(path);
00093
00094
00095 IntIntTbl visited( 1000);
00096 int lineNum = 1, dummy;
00097 unsigned totalCnt = 0U, uniqueCnt = 0U, skipCnt = 0U;
00098 unsigned long totalSz = 0UL;
00099 ShortId sid;
00100 while (true) {
00101 try {
00102 sid = hexrd.Next();
00103 } catch (const HexReader::BadValue &v) {
00104 if (warn) {
00105 os << " Warning: skipping illegal ShortId on line "
00106 << v.lineNum << ": '" << v.str << "'" << endl;
00107 }
00108 continue;
00109 }
00110 if (sid == 0) break;
00111
00112
00113 totalCnt++;
00114 if (!visited.Get(sid, dummy)) {
00115
00116 bool inTbl = visited.Put(sid, 1); assert(!inTbl);
00117
00118
00119 char *nm = SourceOrDerived::shortIdToName(sid, false);
00120 struct stat stat_buff;
00121 if (stat(nm, &stat_buff) != 0) {
00122 if (warn) {
00123 os << " Warning: stat(2) failed on '" << nm
00124 << "'; skipping..." << endl;
00125 }
00126 skipCnt++;
00127 } else {
00128 uniqueCnt++;
00129 totalSz += stat_buff.st_size;
00130 }
00131 delete nm;
00132 }
00133 lineNum++;
00134 }
00135
00136
00137 os << " Total files processed = " << totalCnt << endl;
00138 os << " Unique files processed = " << uniqueCnt << endl;
00139 os << " Unique files skipped = " << skipCnt << endl;
00140 os << " Total size of unique files = "
00141 << FormattedSz((double)totalSz) << endl;
00142 os << " Mean size of unique files = "
00143 << FormattedSz(((double)totalSz)/((double)uniqueCnt)) << endl;
00144 }
00145
00146 int main(int argc, char *argv[])
00147 {
00148
00149 int arg = 1;
00150 bool warn = false;
00151 if (argc <= 1) Syntax("too few arguments");
00152 while (*argv[arg] == '-') {
00153 if (strcmp(argv[arg], "-w") == 0) {
00154 warn = true;
00155 } else {
00156 Syntax("unrecognized option", argv[arg]);
00157 }
00158 arg++;
00159 }
00160
00161
00162 for (; arg < argc; arg++) {
00163 char *path = FileName(argv[arg]);
00164 try {
00165 Process(cout, path, warn);
00166 } catch (FS::DoesNotExist) {
00167 cerr << "Error: file " << path
00168 << " does not exist; continuing..." << endl;
00169 } catch (const FS::Failure &f) {
00170 cerr << "Error: " << f << "; continuing..." << endl;
00171 }
00172 }
00173 return 0;
00174 }