/* This program merges binplace placefiles. It reads in the files named on the command line, and writes out a merged placefile to stdout. */ #include "yvals.h" #pragma warning(disable:4100) #pragma warning(disable:4663) #pragma warning(disable:4511) #pragma warning(disable:4512) #pragma warning(disable:4127) #include #include #include #include #include #include #include #include #include "strtok_r.h" #include "windows.h" const char comment_char = ';'; const char comment_chars[] = { comment_char , 0 }; const char horizontal_whitespace_chars[] = { ' ', '\t', 0 }; const char destination_delim = ':'; const char destination_delims[] = { destination_delim, 0 }; class String_t : public std::string { typedef std::string Base; public: String_t(const std::string & s) : Base(s) { } String_t() { } ~String_t() { } String_t(const String_t & s) : Base(s) { } String_t(const char * s) : Base(s) { } bool operator<( const String_t & s) const { return _stricmp(c_str(), s.c_str()) < 0; } bool operator==( const String_t & s) const { return _stricmp(c_str(), s.c_str()) == 0; } }; class File_t : public std::map > { public: void Read( const char * filename ); }; class CMutableString { public: CMutableString() { } CMutableString(const char * s) { size_t len = strlen(s); this->chars.resize(len + 1); strcpy(&this->chars[0], s); } size_t length() const { return ::strlen(&chars[0]); } void operator=(const CMutableString & t) { if (&t == this) return; this->chars = t.chars; } void operator=(const char * s) { // // s may point into chars, and resize may realloc, so use a temp // CMutableString temp(s); std::swap(this->chars, temp.chars); } operator char * () { return &chars[0]; } std::vector chars; }; class CStringTokenizer { public: CStringTokenizer() : state(0) { } ~CStringTokenizer() { } char * operator()(char * string, const char * delims) { return strtok_r(string, delims, &state); } char * state; }; void TrimHorizontalWhitespaceFromEnds(char * & s) { s += strspn(s, horizontal_whitespace_chars); char * q = s + strlen(s); while (q != s && strchr(horizontal_whitespace_chars, *q) != NULL) { *q = 0; q -= 1; } } void File_t::Read(const char * filename) { String_t line; std::ifstream file; CMutableString mutable_line; char * p = 0; file.open(filename, std::ios_base::in); while (std::getline(file, line)) { mutable_line = line.c_str(); p = mutable_line; p += strspn(p, horizontal_whitespace_chars); if (p[0] == 0) continue; if (strchr(comment_chars, p[0]) != NULL) continue; char * comment = strchr(p, comment_char); if (comment != NULL) *comment = 0; mutable_line = p; p = mutable_line; const char * image_name = p; p += strcspn(p, horizontal_whitespace_chars); *p = 0; const String_t image_name_string = image_name; p += 1; p += strspn(p, horizontal_whitespace_chars); char * destinations = p; TrimHorizontalWhitespaceFromEnds(destinations); CStringTokenizer tokenize; for ( char * destination = tokenize(destinations, destination_delims) ; destination != NULL ; destination = tokenize(NULL, destination_delims) ) { (*this)[image_name_string].insert(destination); //printf("%s -> %s\n", image_name, destination); } } } void MergePlacefiles(int nfiles, char ** filenames) { File_t accum; if (nfiles == 0) return; for ( int i = 0 ; i < nfiles - 1; ++i ) { accum.Read(filenames[i]); } DeleteFileA(filenames[nfiles - 1]); FILE * fout = fopen(filenames[nfiles - 1], "w"); if (fout == NULL) { fprintf(stderr, "Error fopen(%s)\n", filenames[nfiles - 1]); exit(-1); } for ( File_t::const_iterator it = accum.begin(); it != accum.end(); ++it ) { fprintf(fout, "%s ", it->first.c_str()); bool first = true; for ( std::set::const_iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ) { if (!first) fprintf(fout, ":"); fprintf(fout, "%s", it2->c_str()); first = false; } fprintf(fout, "\n"); } fclose(fout); } int __cdecl main(int argc, char ** argv) { MergePlacefiles(argc - 1 , argv + 1); return 0; }