00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifdef HAVE_CONFIG_H
00023 # include <config.h>
00024 #endif
00025
00026 #ifndef ALPHA_LINUX_CXX
00027 # include <cctype>
00028 # include <cstdio>
00029 # include <cstdlib>
00030 # include <cstring>
00031 # include <fstream>
00032 #endif
00033 #include <map>
00034 #include <list>
00035 #ifdef MACOS
00036 #include <stat.h>
00037 #elif !defined(UNDER_CE)
00038 #include <sys/stat.h>
00039 #endif
00040 #include <unistd.h>
00041
00042 #ifdef WIN32
00043 #include <windows.h>
00044 #endif
00045
00046 #include <exception>
00047 #include "exceptions.h"
00048 #include "utils.h"
00049
00050
00051 using std::cerr;
00052 using std::string;
00053 using std::ios;
00054
00055
00056
00057 static void switch_slashes(string & name);
00058 static bool base_to_uppercase(string& str, int count);
00059
00060
00061
00062 inline int stat(const std::string &file_name, struct stat *buf)
00063 {
00064 return stat(file_name.c_str(),buf);
00065 }
00066
00067
00068
00069 static std::map<string, string> path_map;
00070 static std::map<string, string> stored_path_map;
00071
00072 void store_system_paths()
00073 {
00074 stored_path_map = path_map;
00075 }
00076
00077 void reset_system_paths()
00078 {
00079 path_map = stored_path_map;
00080 }
00081
00082 void add_system_path(const string& key, const string& value)
00083 {
00084 if (!value.empty()) {
00085 path_map[key] = value;
00086 } else {
00087 clear_system_path(key);
00088 }
00089 }
00090
00091 void clone_system_path(const string& new_key, const string& old_key)
00092 {
00093 if (is_system_path_defined(old_key)) {
00094 path_map[new_key] = path_map[old_key];
00095 } else {
00096 clear_system_path(new_key);
00097 }
00098 }
00099
00100 void clear_system_path(const string& key)
00101 {
00102 std::map<string, string>::iterator iter = path_map.find(key);
00103 if (iter != path_map.end())
00104 path_map.erase(iter);
00105 }
00106
00107
00108
00109
00110 bool is_system_path_defined(const string& path)
00111 {
00112 return (path_map.find(path) != path_map.end());
00113 }
00114
00115
00116
00117
00118
00119 string get_system_path(const string &path)
00120 {
00121 string new_path;
00122 string::size_type pos;
00123 string::size_type pos2;
00124
00125 #if defined(__MORPHOS__) || defined(AMIGA)
00126 pos = path.find( "../" );
00127 if( pos != string::npos )
00128 new_path = path.substr( 0, pos )+path.substr( pos+2 );
00129 else
00130 new_path = path;
00131
00132 pos = new_path.find( "./" );
00133 if( pos != string::npos )
00134 new_path = new_path.substr( 0, pos )+new_path.substr( pos+2 );
00135
00136 pos = new_path.find('>');
00137 pos2 = new_path.find('<');
00138
00139 if(pos != string::npos && pos2 == 0)
00140 {
00141 pos += 1;
00142
00143 string syspath = new_path.substr(0, pos);
00144 if (is_system_path_defined(syspath)) {
00145 string new_prefix = path_map[syspath];
00146 new_path = new_prefix + new_path.substr(pos);
00147 }
00148 }
00149 #else
00150 pos = path.find('>');
00151 pos2 = path.find('<');
00152
00153 if(pos == string::npos || pos2 != 0) {
00154 new_path = path;
00155 }
00156 else
00157 {
00158 pos += 1;
00159
00160 string syspath = path.substr(0, pos);
00161 if (is_system_path_defined(syspath)) {
00162 string new_prefix = path_map[syspath];
00163 new_path = new_prefix + path.substr(pos);
00164 } else {
00165 new_path = path;
00166 }
00167 }
00168 #endif
00169 switch_slashes(new_path);
00170 #ifdef WIN32
00171 if (*(new_path.end()-1) == '/' || *(new_path.end()-1) == '\\') {
00172 std::cerr << "Trailing slash in path: \"" << new_path << "\"" << std::endl << "...compensating, but go complain to Colourless anyway" << std::endl;
00173 new_path += '.';
00174 }
00175 #ifdef NO_WIN32_PATH_SPACES
00176 pos = new_path.find('*');
00177 pos2 = new_path.find('?');
00178 string::size_type pos3 = new_path.find(' ');
00179
00180
00181
00182 if (pos == pos2 && pos3 != string::npos) {
00183 int num_chars = GetShortPathName(new_path.c_str(), NULL, 0);
00184 if (num_chars > 0) {
00185 char *short_path = new char [num_chars+1];
00186 GetShortPathName(new_path.c_str(), short_path, num_chars+1);
00187 new_path = short_path;
00188 delete [] short_path;
00189 }
00190
00191 }
00192 #endif
00193 #endif
00194 return new_path;
00195 }
00196
00197
00198
00199
00200
00201
00202
00203
00204 void to_uppercase(string &str)
00205 {
00206 for(string::iterator X = str.begin(); X != str.end(); ++X)
00207 {
00208 #if (defined(BEOS) || defined(OPENBSD) || defined(CYGWIN) || defined(__MORPHOS__))
00209 if ((*X >= 'a') && (*X <= 'z')) *X -= 32;
00210 #else
00211 *X = std::toupper(*X);
00212 #endif
00213 }
00214 }
00215
00216 string to_uppercase(const std::string &str)
00217 {
00218 string s(str);
00219 to_uppercase(s);
00220 return s;
00221 }
00222
00223
00224
00225
00226
00227
00228 static bool base_to_uppercase(string& str, int count)
00229 {
00230 if (count <= 0) return true;
00231
00232 int todo = count;
00233
00234 string::reverse_iterator X;
00235 for(X = str.rbegin(); X != str.rend(); ++X)
00236 {
00237
00238 if (*X == '/' || *X == '\\' || *X == ':')
00239 todo--;
00240 if (todo <= 0)
00241 break;
00242
00243 #if (defined(BEOS) || defined(OPENBSD) || defined(CYGWIN) || defined(__MORPHOS__))
00244 if ((*X >= 'a') && (*X <= 'z')) *X -= 32;
00245 #else
00246 *X = std::toupper(*X);
00247 #endif
00248 }
00249 if (X == str.rend())
00250 todo--;
00251
00252
00253 return (todo <= 0);
00254 }
00255
00256
00257
00258 static void switch_slashes(
00259 string & name
00260 )
00261 {
00262 #ifdef WIN32
00263 for(string::iterator X = name.begin(); X != name.end(); ++X)
00264 {
00265 if(*X == '/' )
00266 *X = '\\';
00267 }
00268 #elif defined(MACOS)
00269
00270
00271
00272
00273 string::size_type begIdx, endIdx;;
00274 string component;
00275 string new_name;
00276
00277 if( name.at(0) != '/' )
00278 new_name = ":";
00279
00280 begIdx = name.find_first_not_of('/');
00281 while( begIdx != string::npos )
00282 {
00283 endIdx = name.find_first_of('/', begIdx);
00284 if( endIdx == std::string::npos )
00285 component = name.substr(begIdx);
00286 else
00287 component = name.substr(begIdx, endIdx-begIdx);
00288 if( component == ".." )
00289 new_name += ":";
00290 else if( !component.empty() && component != "." )
00291 {
00292 new_name += component;
00293 if( endIdx != std::string::npos )
00294 new_name += ":";
00295 }
00296 begIdx = name.find_first_not_of('/', endIdx);
00297 }
00298
00299 name = new_name;
00300 #else
00301
00302 #endif
00303 }
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313 bool U7open
00314 (
00315 std::ifstream& in,
00316 const char *fname,
00317 bool is_text
00318 )
00319 {
00320 #if defined(MACOS) || (__GNUG__ > 2)
00321 std::ios_base::openmode mode = std::ios::in;
00322 if (!is_text) mode |= std::ios::binary;
00323 #elif defined(XWIN)
00324 int mode = std::ios::in;
00325 #else
00326 int mode = std::ios::in;
00327 if (!is_text) mode |= std::ios::binary;
00328 #endif
00329 string name = get_system_path(fname);
00330
00331 int uppercasecount = 0;
00332 do {
00333
00334
00335 in.clear();
00336 try {
00337
00338 in.open(name.c_str(), mode);
00339 } catch (std::exception &)
00340 {}
00341 if (in.good() && !in.fail()) {
00342
00343 return true;
00344 }
00345 } while (base_to_uppercase(name, ++uppercasecount));
00346
00347
00348 throw (file_open_exception(get_system_path(fname)));
00349 return false;
00350 }
00351
00352 #ifdef ALPHA_LINUX_CXX
00353
00354
00355
00356
00357
00358
00359 bool U7open(std::ifstream& in,
00360 const char *fname)
00361 {
00362 return U7open(in, fname, false);
00363 }
00364 #endif
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374 bool U7open
00375 (
00376 std::ofstream& out,
00377 const char *fname,
00378 bool is_text
00379 )
00380 {
00381 #if defined(MACOS) || (__GNUG__ > 2)
00382 std::ios_base::openmode mode = std::ios::out | std::ios::trunc;
00383 if (!is_text) mode |= std::ios::binary;
00384 #elif defined(XWIN)
00385 int mode = std::ios::out | std::ios::trunc;
00386 #else
00387 int mode = std::ios::out | std::ios::trunc;
00388 if (!is_text) mode |= std::ios::binary;
00389 #endif
00390 string name = get_system_path(fname);
00391
00392
00393
00394 out.clear();
00395
00396 int uppercasecount = 0;
00397 do {
00398 out.open(name.c_str(), mode);
00399 if (out.good())
00400 return true;
00401 out.clear();
00402 } while (base_to_uppercase(name, ++uppercasecount));
00403
00404
00405 throw (file_open_exception(get_system_path(fname)));
00406 return false;
00407 }
00408
00409 #ifdef ALPHA_LINUX_CXX
00410
00411
00412
00413
00414
00415
00416 bool U7open(std::ofstream& out,
00417 const char *fname)
00418 {
00419 return U7open(out, fname, false);
00420 }
00421 #endif
00422
00423
00424
00425
00426
00427
00428
00429
00430 std::FILE* U7open
00431 (
00432 const char *fname,
00433 const char *mode
00434 )
00435 {
00436 std::FILE* f;
00437 string name = get_system_path(fname);
00438
00439 int uppercasecount = 0;
00440 do {
00441 f = std::fopen(name.c_str(), mode);
00442 if (f)
00443 return f;
00444 } while (base_to_uppercase(name, ++uppercasecount));
00445
00446
00447 throw (file_open_exception(get_system_path(fname)));
00448 return 0;
00449 }
00450
00451
00452
00453
00454
00455
00456 void U7remove
00457 (
00458 const char *fname
00459 )
00460 {
00461 string name = get_system_path(fname);
00462
00463 #if defined(WIN32) && defined(UNICODE)
00464 const char *n = name.c_str();
00465 int nLen = std::strlen(n)+1;
00466 LPTSTR lpszT = (LPTSTR) alloca(nLen*2);
00467 MultiByteToWideChar(CP_ACP, 0, n, -1, lpszT, nLen);
00468 DeleteFile(lpszT);
00469 #else
00470
00471 bool exists;
00472 struct stat sbuf;
00473
00474 int uppercasecount = 0;
00475 do {
00476 exists = (stat(name, &sbuf) == 0);
00477 if (exists) {
00478 std::remove(name.c_str());
00479 }
00480 } while (base_to_uppercase(name, ++uppercasecount));
00481 std::remove(name.c_str());
00482 #endif
00483 }
00484
00485
00486
00487
00488
00489 bool U7exists
00490 (
00491 const char *fname
00492 )
00493 {
00494 string name = get_system_path(fname);
00495
00496 #ifdef UNDER_CE // This is a bit of a hack for WinCE
00497 const char *n = name.c_str();
00498 int nLen = std::strlen(n)+1;
00499 LPTSTR lpszT = (LPTSTR) alloca(nLen*2);
00500 MultiByteToWideChar(CP_ACP, 0, n, -1, lpszT, nLen);
00501 return GetFileAttributes(lpszT) != 0xFFFFFFFF;
00502 #else
00503
00504 bool exists;
00505 struct stat sbuf;
00506
00507 int uppercasecount = 0;
00508 do {
00509 exists = (stat(name, &sbuf) == 0);
00510 if (exists)
00511 return true;
00512 } while (base_to_uppercase(name, ++uppercasecount));
00513
00514
00515 return false;
00516 #endif
00517 }
00518
00519
00520
00521
00522
00523 int U7mkdir
00524 (
00525 const char *dirname,
00526 int mode
00527 )
00528 {
00529 string name = get_system_path(dirname);
00530 #if (defined(MACOSX) || defined(BEOS))
00531
00532 string::size_type pos = name.find_last_not_of('/');
00533 if (pos != string::npos)
00534 name.resize(pos+1);
00535 #endif
00536 #if defined(WIN32) && defined(UNICODE)
00537 const char *n = name.c_str();
00538 int nLen = std::strlen(n)+1;
00539 LPTSTR lpszT = (LPTSTR) alloca(nLen*2);
00540 MultiByteToWideChar(CP_ACP, 0, n, -1, lpszT, nLen);
00541 return CreateDirectory(lpszT, NULL);
00542 #elif defined(WIN32)
00543 return mkdir(name.c_str());
00544 #else
00545 return mkdir(name.c_str(), mode);
00546 #endif
00547 }
00548
00549
00550 #ifndef UNDER_CE
00551
00552
00553
00554
00555
00556
00557
00558 int U7chdir
00559 (
00560 const char *dirname
00561 )
00562 {
00563 #ifdef MACOS
00564 string name(dirname);
00565 switch_slashes(name);
00566 return chdir(name.c_str());
00567 #else
00568 return chdir(dirname);
00569 #endif
00570 }
00571
00572
00573
00574
00575
00576
00577 void U7copy
00578 (
00579 const char *src,
00580 const char *dest
00581 )
00582 {
00583 std::ifstream in;
00584 std::ofstream out;
00585 try {
00586 U7open(in, src);
00587 U7open(out, dest);
00588 } catch (exult_exception& e) {
00589 in.close();
00590 out.close();
00591 throw (e);
00592 }
00593 const int bufsize = 0x8000;
00594 unsigned char *buf = new unsigned char[0x8000];
00595 in.seekg(0, ios::end);
00596 int filesize = in.tellg();
00597 in.seekg(0, ios::beg);
00598 while (filesize > 0)
00599 {
00600 int toread = bufsize < filesize ? bufsize : filesize;
00601 in.read(reinterpret_cast<char *>(buf), toread);
00602 out.write(reinterpret_cast<char *>(buf), toread);
00603 filesize -= toread;
00604 }
00605 out.flush();
00606 delete [] buf;
00607 bool inok = in.good(), outok = out.good();
00608 in.close();
00609 out.close();
00610 if (!inok)
00611 throw (file_read_exception((const char *)src));
00612 if (!outok)
00613 throw (file_write_exception((const char *)dest));
00614
00615 return;
00616 }
00617 #endif //UNDER_CE
00618
00619
00620
00621
00622
00623
00624
00625 int Log2
00626 (
00627 uint32 n
00628 )
00629 {
00630 int result = 0;
00631 for (n = n>>1; n; n = n>>1)
00632 result++;
00633 return result;
00634 }
00635
00636
00637
00638
00639
00640 char *newstrdup(const char *s)
00641 {
00642 if(!s)
00643 throw (std::invalid_argument("NULL pointer passed to newstrdup"));
00644 char *ret=new char[std::strlen(s)+1];
00645 std::strcpy(ret,s);
00646 return ret;
00647 }