1: 
   2: // Copyright (c) 1999-2011 by Digital Mars
   3: // All Rights Reserved
   4: // written by Walter Bright
   5: // http://www.digitalmars.com
   6: // License for redistribution is by either the Artistic License
   7: // in artistic.txt, or the GNU General Public License in gnu.txt.
   8: // See the included readme.txt for details.
   9: 
  10: #define POSIX (linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4)
  11: 
  12: #include <stdio.h>
  13: #include <stdlib.h>
  14: #include <stdarg.h>
  15: #include <limits.h>
  16: #include <string.h>
  17: #include <stdint.h>
  18: static char __file__[] = __FILE__;      /* for tassert.h                */
  19: #include        "tassert.h"
  20: 
  21: #if (defined (__SVR4) && defined (__sun))
  22: #include <alloca.h>
  23: #endif
  24: 
  25: #if _MSC_VER ||__MINGW32__
  26: #include <malloc.h>
  27: #include <string>
  28: #endif
  29: 
  30: #if _WIN32
  31: #include <windows.h>
  32: #include <direct.h>
  33: #include <errno.h>
  34: #endif
  35: 
  36: #if POSIX
  37: #include <sys/types.h>
  38: #include <sys/stat.h>
  39: #include <fcntl.h>
  40: #include <errno.h>
  41: #include <unistd.h>
  42: #include <utime.h>
  43: #endif
  44: 
  45: #include "port.h"
  46: #include "root.h"
  47: #include "dchar.h"
  48: #include "rmem.h"
  49: 
  50: #if 0 //__SC__ //def DEBUG
  51: extern "C" void __cdecl _assert(void *e, void *f, unsigned line)
  52: {
  53:     printf("Assert('%s','%s',%d)\n",e,f,line);
  54:     fflush(stdout);
  55:     *(char *)0 = 0;
  56: }
  57: #endif
  58: 
  59: 
  60: /*************************************
  61:  * Convert wchar string to ascii string.
  62:  */
  63: 
  64: char *wchar2ascii(wchar_t *us)
  65: {
  66:     return wchar2ascii(us, wcslen(us));
  67: }
  68: 
  69: char *wchar2ascii(wchar_t *us, unsigned len)
  70: {
  71:     unsigned i;
  72:     char *p;
  73: 
  74:     p = (char *)mem.malloc(len + 1);
  75:     for (i = 0; i <= len; i++)
  76:         p[i] = (char) us[i];
  77:     return p;
  78: }
  79: 
  80: int wcharIsAscii(wchar_t *us)
  81: {
  82:     return wcharIsAscii(us, wcslen(us));
  83: }
  84: 
  85: int wcharIsAscii(wchar_t *us, unsigned len)
  86: {
  87:     unsigned i;
  88: 
  89:     for (i = 0; i <= len; i++)
  90:     {
  91:         if (us[i] & ~0xFF)      // if high bits set
  92:             return 0;           // it's not ascii
  93:     }
  94:     return 1;
  95: }
  96: 
  97: 
  98: /***********************************
  99:  * Compare length-prefixed strings (bstr).
 100:  */
 101: 
 102: int bstrcmp(unsigned char *b1, unsigned char *b2)
 103: {
 104:     return (*b1 == *b2 && memcmp(b1 + 1, b2 + 1, *b2) == 0) ? 0 : 1;
 105: }
 106: 
 107: /***************************************
 108:  * Convert bstr into a malloc'd string.
 109:  */
 110: 
 111: char *bstr2str(unsigned char *b)
 112: {
 113:     char *s;
 114:     unsigned len;
 115: 
 116:     len = *b;
 117:     s = (char *) mem.malloc(len + 1);
 118:     s[len] = 0;
 119:     return (char *)memcpy(s,b + 1,len);
 120: }
 121: 
 122: /**************************************
 123:  * Print error message and exit.
 124:  */
 125: 
 126: void error(const char *format, ...)
 127: {
 128:     va_list ap;
 129: 
 130:     va_start(ap, format);
 131:     printf("Error: ");
 132:     vprintf(format, ap);
 133:     va_end( ap );
 134:     printf("\n");
 135:     fflush(stdout);
 136: 
 137:     exit(EXIT_FAILURE);
 138: }
 139: 
 140: #if M_UNICODE
 141: void error(const dchar *format, ...)
 142: {
 143:     va_list ap;
 144: 
 145:     va_start(ap, format);
 146:     printf("Error: ");
 147:     vwprintf(format, ap);
 148:     va_end( ap );
 149:     printf("\n");
 150:     fflush(stdout);
 151: 
 152:     exit(EXIT_FAILURE);
 153: }
 154: #endif
 155: 
 156: void error_mem()
 157: {
 158:     error("out of memory");
 159: }
 160: 
 161: /**************************************
 162:  * Print warning message.
 163:  */
 164: 
 165: void warning(const char *format, ...)
 166: {
 167:     va_list ap;
 168: 
 169:     va_start(ap, format);
 170:     printf("Warning: ");
 171:     vprintf(format, ap);
 172:     va_end( ap );
 173:     printf("\n");
 174:     fflush(stdout);
 175: }
 176: 
 177: /****************************** Object ********************************/
 178: 
 179: int Object::equals(Object *o)
 180: {
 181:     return o == this;
 182: }
 183: 
 184: hash_t Object::hashCode()
 185: {
 186:     return (hash_t) this;
 187: }
 188: 
 189: int Object::compare(Object *obj)
 190: {
 191:     return this - obj;
 192: }
 193: 
 194: void Object::print()
 195: {
 196:     printf("%s %p\n", toChars(), this);
 197: }
 198: 
 199: char *Object::toChars()
 200: {
 201:     return (char *)"Object";
 202: }
 203: 
 204: dchar *Object::toDchars()
 205: {
 206: #if M_UNICODE
 207:     return L"Object";
 208: #else
 209:     return toChars();
 210: #endif
 211: }
 212: 
 213: int Object::dyncast()
 214: {
 215:     return 0;
 216: }
 217: 
 218: void Object::toBuffer(OutBuffer *b)
 219: {
 220:     b->writestring("Object");
 221: }
 222: 
 223: void Object::mark()
 224: {
 225: }
 226: 
 227: /****************************** String ********************************/
 228: 
 229: String::String(char *str, int ref)
 230: {
 231:     this->str = ref ? str : mem.strdup(str);
 232:     this->ref = ref;
 233: }
 234: 
 235: String::~String()
 236: {
 237:     mem.free(str);
 238: }
 239: 
 240: void String::mark()
 241: {
 242:     mem.mark(str);
 243: }
 244: 
 245: hash_t String::calcHash(const char *str, size_t len)
 246: {
 247:     hash_t hash = 0;
 248: 
 249:     for (;;)
 250:     {
 251:         switch (len)
 252:         {
 253:             case 0:
 254:                 return hash;
 255: 
 256:             case 1:
 257:                 hash *= 37;
 258:                 hash += *(uint8_t *)str;
 259:                 return hash;
 260: 
 261:             case 2:
 262:                 hash *= 37;
 263:                 hash += *(uint16_t *)str;
 264:                 return hash;
 265: 
 266:             case 3:
 267:                 hash *= 37;
 268:                 hash += (*(uint16_t *)str << 8) +
 269:                         ((uint8_t *)str)[2];
 270:                 return hash;
 271: 
 272:             default:
 273:                 hash *= 37;
 274:                 hash += *(uint32_t *)str;
 275:                 str += 4;
 276:                 len -= 4;
 277:                 break;
 278:         }
 279:     }
 280: }
 281: 
 282: hash_t String::calcHash(const char *str)
 283: {
 284:     return calcHash(str, strlen(str));
 285: }
 286: 
 287: hash_t String::hashCode()
 288: {
 289:     return calcHash(str, strlen(str));
 290: }
 291: 
 292: unsigned String::len()
 293: {
 294:     return strlen(str);
 295: }
 296: 
 297: int String::equals(Object *obj)
 298: {
 299:     return strcmp(str,((String *)obj)->str) == 0;
 300: }
 301: 
 302: int String::compare(Object *obj)
 303: {
 304:     return strcmp(str,((String *)obj)->str);
 305: }
 306: 
 307: char *String::toChars()
 308: {
 309:     return str;
 310: }
 311: 
 312: void String::print()
 313: {
 314:     printf("String '%s'\n",str);
 315: }
 316: 
 317: 
 318: /****************************** FileName ********************************/
 319: 
 320: FileName::FileName(char *str, int ref)
 321:     : String(str,ref)
 322: {
 323: }
 324: 
 325: char *FileName::combine(const char *path, const char *name)
 326: {   char *f;
 327:     size_t pathlen;
 328:     size_t namelen;
 329: 
 330:     if (!path || !*path)
 331:         return (char *)name;
 332:     pathlen = strlen(path);
 333:     namelen = strlen(name);
 334:     f = (char *)mem.malloc(pathlen + 1 + namelen + 1);
 335:     memcpy(f, path, pathlen);
 336: #if POSIX
 337:     if (path[pathlen - 1] != '/')
 338:     {   f[pathlen] = '/';
 339:         pathlen++;
 340:     }
 341: #elif _WIN32
 342:     if (path[pathlen - 1] != '\\' &&
 343:         path[pathlen - 1] != '/'  &&
 344:         path[pathlen - 1] != ':')
 345:     {   f[pathlen] = '\\';
 346:         pathlen++;
 347:     }
 348: #else
 349:     assert(0);
 350: #endif
 351:     memcpy(f + pathlen, name, namelen + 1);
 352:     return f;
 353: }
 354: 
 355: FileName::FileName(char *path, char *name)
 356:     : String(combine(path,name),1)
 357: {
 358: }
 359: 
 360: // Split a path into an Array of paths
 361: Strings *FileName::splitPath(const char *path)
 362: {
 363:     char c = 0;                         // unnecessary initializer is for VC /W4
 364:     const char *p;
 365:     OutBuffer buf;
 366:     Strings *array;
 367: 
 368:     array = new Strings();
 369:     if (path)
 370:     {
 371:         p = path;
 372:         do
 373:         {   char instring = 0;
 374: 
 375:             while (isspace(*p))         // skip leading whitespace
warning C6328: 'const char' passed as parameter '1' when 'unsigned char' is required in call to 'isspace'
376: p++; 377: buf.reserve(strlen(p) + 1); // guess size of path 378: for (; ; p++) 379: { 380: c = *p; 381: switch (c) 382: { 383: case '"': 384: instring ^= 1; // toggle inside/outside of string 385: continue; 386: 387: #if MACINTOSH 388: case ',': 389: #endif 390: #if _WIN32 391: case ';': 392: #endif 393: #if POSIX 394: case ':': 395: #endif 396: p++; 397: break; // note that ; cannot appear as part 398: // of a path, quotes won't protect it 399: 400: case 0x1A: // ^Z means end of file 401: case 0: 402: break; 403: 404: case '\r': 405: continue; // ignore carriage returns 406: 407: #if POSIX 408: case '~': 409: buf.writestring(getenv("HOME")); 410: continue; 411: #endif 412: 413: #if 0 414: case ' ': 415: case '\t': // tabs in filenames? 416: if (!instring) // if not in string 417: break; // treat as end of path 418: #endif 419: default: 420: buf.writeByte(c); 421: continue; 422: } 423: break; 424: } 425: if (buf.offset) // if path is not empty 426: { 427: buf.writeByte(0); // to asciiz 428: array->push(buf.extractData()); 429: } 430: } while (c); 431: } 432: return array; 433: } 434: 435: hash_t FileName::hashCode() 436: { 437: #if _WIN32 438: // We need a different hashCode because it must be case-insensitive 439: size_t len = strlen(str); 440: hash_t hash = 0; 441: unsigned char *s = (unsigned char *)str; 442: 443: for (;;) 444: { 445: switch (len) 446: { 447: case 0: 448: return hash; 449: 450: case 1: 451: hash *= 37; 452: hash += *(uint8_t *)s | 0x20; 453: return hash; 454: 455: case 2: 456: hash *= 37; 457: hash += *(uint16_t *)s | 0x2020; 458: return hash; 459: 460: case 3: 461: hash *= 37; 462: hash += ((*(uint16_t *)s << 8) + 463: ((uint8_t *)s)[2]) | 0x202020; 464: break; 465: 466: default: 467: hash *= 37; 468: hash += *(uint32_t *)s | 0x20202020; 469: s += 4; 470: len -= 4; 471: break; 472: } 473: } 474: #else 475: // darwin HFS is case insensitive, though... 476: return String::hashCode(); 477: #endif 478: } 479: 480: int FileName::compare(Object *obj) 481: { 482: return compare(str, ((FileName *)obj)->str); 483: } 484: 485: int FileName::compare(const char *name1, const char *name2) 486: { 487: #if _WIN32 488: return stricmp(name1, name2);
warning C4996: 'stricmp': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _stricmp. See online help for details. c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(246) : see declaration of 'stricmp'
489: #else 490: return strcmp(name1, name2); 491: #endif 492: } 493: 494: int FileName::equals(Object *obj) 495: { 496: return compare(obj) == 0; 497: } 498: 499: int FileName::equals(const char *name1, const char *name2) 500: { 501: return compare(name1, name2) == 0; 502: } 503: 504: /************************************ 505: * Return !=0 if absolute path name. 506: */ 507: 508: int FileName::absolute(const char *name) 509: { 510: #if _WIN32 511: return (*name == '\\') || 512: (*name == '/') || 513: (*name && name[1] == ':'); 514: #elif POSIX 515: return (*name == '/'); 516: #else 517: assert(0); 518: #endif 519: } 520: 521: /******************************** 522: * Return filename extension (read-only). 523: * Points past '.' of extension. 524: * If there isn't one, return NULL. 525: */ 526: 527: char *FileName::ext(const char *str) 528: { 529: char *e; 530: size_t len = strlen(str); 531: 532: e = (char *)str + len; 533: for (;;) 534: { 535: switch (*e) 536: { case '.': 537: return e + 1; 538: #if POSIX 539: case '/': 540: break; 541: #endif 542: #if _WIN32 543: case '\\': 544: case ':': 545: case '/': 546: break; 547: #endif 548: default: 549: if (e == str) 550: break; 551: e--; 552: continue; 553: } 554: return NULL; 555: } 556: } 557: 558: char *FileName::ext() 559: { 560: return ext(str); 561: } 562: 563: /******************************** 564: * Return mem.malloc'd filename with extension removed. 565: */ 566: 567: char *FileName::removeExt(const char *str) 568: { 569: const char *e = ext(str); 570: if (e) 571: { size_t len = (e - str) - 1; 572: char *n = (char *)mem.malloc(len + 1); 573: memcpy(n, str, len); 574: n[len] = 0; 575: return n; 576: } 577: return mem.strdup(str); 578: } 579: 580: /******************************** 581: * Return filename name excluding path (read-only). 582: */ 583: 584: char *FileName::name(const char *str) 585: { 586: char *e; 587: size_t len = strlen(str); 588: 589: e = (char *)str + len; 590: for (;;) 591: { 592: switch (*e) 593: { 594: #if POSIX 595: case '/': 596: return e + 1; 597: #endif 598: #if _WIN32 599: case '/': 600: case '\\': 601: return e + 1; 602: case ':': 603: /* The ':' is a drive letter only if it is the second 604: * character or the last character, 605: * otherwise it is an ADS (Alternate Data Stream) separator. 606: * Consider ADS separators as part of the file name. 607: */ 608: if (e == str + 1 || e == str + len - 1) 609: return e + 1; 610: #endif 611: default: 612: if (e == str) 613: break; 614: e--; 615: continue; 616: } 617: return e; 618: } 619: } 620: 621: char *FileName::name() 622: { 623: return name(str); 624: } 625: 626: /************************************** 627: * Return path portion of str. 628: * Path will does not include trailing path separator. 629: */ 630: 631: char *FileName::path(const char *str) 632: { 633: char *n = name(str); 634: char *path; 635: size_t pathlen; 636: 637: if (n > str) 638: { 639: #if POSIX 640: if (n[-1] == '/') 641: n--; 642: #elif _WIN32 643: if (n[-1] == '\\' || n[-1] == '/') 644: n--; 645: #else 646: assert(0); 647: #endif 648: } 649: pathlen = n - str; 650: path = (char *)mem.malloc(pathlen + 1); 651: memcpy(path, str, pathlen); 652: path[pathlen] = 0; 653: return path; 654: } 655: 656: /************************************** 657: * Replace filename portion of path. 658: */ 659: 660: const char *FileName::replaceName(const char *path, const char *name) 661: { char *f; 662: char *n; 663: size_t pathlen; 664: size_t namelen; 665: 666: if (absolute(name)) 667: return name; 668: 669: n = FileName::name(path); 670: if (n == path) 671: return name; 672: pathlen = n - path; 673: namelen = strlen(name); 674: f = (char *)mem.malloc(pathlen + 1 + namelen + 1); 675: memcpy(f, path, pathlen); 676: #if POSIX 677: if (path[pathlen - 1] != '/') 678: { f[pathlen] = '/'; 679: pathlen++; 680: } 681: #elif _WIN32 682: if (path[pathlen - 1] != '\\' && 683: path[pathlen - 1] != '/' && 684: path[pathlen - 1] != ':') 685: { f[pathlen] = '\\'; 686: pathlen++; 687: } 688: #else 689: assert(0); 690: #endif 691: memcpy(f + pathlen, name, namelen + 1); 692: return f; 693: } 694: 695: /*************************** 696: */ 697: 698: FileName *FileName::defaultExt(const char *name, const char *ext) 699: { 700: char *e; 701: char *s; 702: size_t len; 703: size_t extlen; 704: 705: e = FileName::ext(name); 706: if (e) // if already has an extension 707: return new FileName((char *)name, 0); 708: 709: len = strlen(name); 710: extlen = strlen(ext); 711: s = (char *)alloca(len + 1 + extlen + 1);
warning C6255: _alloca indicates failure by raising a stack overflow exception. Consider using _malloca instead
712: memcpy(s,name,len); 713: s[len] = '.'; 714: memcpy(s + len + 1, ext, extlen + 1); 715: return new FileName(s, 0); 716: } 717: 718: /*************************** 719: */ 720: 721: FileName *FileName::forceExt(const char *name, const char *ext) 722: { 723: char *e; 724: char *s; 725: size_t len; 726: size_t extlen; 727: 728: e = FileName::ext(name); 729: if (e) // if already has an extension 730: { 731: len = e - name; 732: extlen = strlen(ext); 733: 734: s = (char *)alloca(len + extlen + 1);
warning C6255: _alloca indicates failure by raising a stack overflow exception. Consider using _malloca instead
735: memcpy(s,name,len); 736: memcpy(s + len, ext, extlen + 1); 737: return new FileName(s, 0); 738: } 739: else 740: return defaultExt(name, ext); // doesn't have one 741: } 742: 743: /****************************** 744: * Return !=0 if extensions match. 745: */ 746: 747: int FileName::equalsExt(const char *ext) 748: { const char *e; 749: 750: e = FileName::ext(); 751: if (!e && !ext) 752: return 1; 753: if (!e || !ext) 754: return 0; 755: #if POSIX 756: return strcmp(e,ext) == 0; 757: #elif _WIN32 758: return stricmp(e,ext) == 0;
warning C4996: 'stricmp': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _stricmp. See online help for details. c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(246) : see declaration of 'stricmp'
759: #else 760: assert(0); 761: #endif 762: } 763: 764: /************************************* 765: * Copy file from this to to. 766: */ 767: 768: void FileName::CopyTo(FileName *to) 769: { 770: File file(this); 771: 772: #if _WIN32 773: file.touchtime = mem.malloc(sizeof(WIN32_FIND_DATAA)); // keep same file time 774: #elif POSIX 775: file.touchtime = mem.malloc(sizeof(struct stat)); // keep same file time 776: #else 777: assert(0); 778: #endif 779: file.readv(); 780: file.name = to; 781: file.writev(); 782: } 783: 784: /************************************* 785: * Search Path for file. 786: * Input: 787: * cwd if !=0, search current directory before searching path 788: */ 789: 790: char *FileName::searchPath(Strings *path, const char *name, int cwd) 791: { 792: if (absolute(name)) 793: { 794: return exists(name) ? (char *)name : NULL; 795: } 796: if (cwd) 797: { 798: if (exists(name)) 799: return (char *)name; 800: } 801: if (path) 802: { unsigned i; 803: 804: for (i = 0; i < path->dim; i++) 805: { 806: char *p = path->tdata()[i]; 807: char *n = combine(p, name); 808: 809: if (exists(n)) 810: return n; 811: } 812: } 813: return NULL; 814: } 815: 816: 817: /************************************* 818: * Search Path for file in a safe manner. 819: * 820: * Be wary of CWE-22: Improper Limitation of a Pathname to a Restricted Directory 821: * ('Path Traversal') attacks. 822: * http://cwe.mitre.org/data/definitions/22.html 823: * More info: 824: * https://www.securecoding.cert.org/confluence/display/seccode/FIO02-C.+Canonicalize+path+names+originating+from+untrusted+sources 825: * Returns: 826: * NULL file not found 827: * !=NULL mem.malloc'd file name 828: */ 829: 830: char *FileName::safeSearchPath(Strings *path, const char *name) 831: { 832: #if _WIN32 833: /* Disallow % / \ : and .. in name characters 834: */ 835: for (const char *p = name; *p; p++) 836: { 837: char c = *p; 838: if (c == '\\' || c == '/' || c == ':' || c == '%' || 839: (c == '.' && p[1] == '.')) 840: { 841: return NULL; 842: } 843: } 844: 845: return FileName::searchPath(path, name, 0); 846: #elif POSIX 847: /* Even with realpath(), we must check for // and disallow it 848: */ 849: for (const char *p = name; *p; p++) 850: { 851: char c = *p; 852: if (c == '/' && p[1] == '/') 853: { 854: return NULL; 855: } 856: } 857: 858: if (path) 859: { unsigned i; 860: 861: /* Each path is converted to a cannonical name and then a check is done to see 862: * that the searched name is really a child one of the the paths searched. 863: */ 864: for (i = 0; i < path->dim; i++) 865: { 866: char *cname = NULL; 867: char *cpath = canonicalName(path->tdata()[i]); 868: //printf("FileName::safeSearchPath(): name=%s; path=%s; cpath=%s\n", 869: // name, (char *)path->data[i], cpath); 870: if (cpath == NULL) 871: goto cont; 872: cname = canonicalName(combine(cpath, name)); 873: //printf("FileName::safeSearchPath(): cname=%s\n", cname); 874: if (cname == NULL) 875: goto cont; 876: //printf("FileName::safeSearchPath(): exists=%i " 877: // "strncmp(cpath, cname, %i)=%i\n", exists(cname), 878: // strlen(cpath), strncmp(cpath, cname, strlen(cpath))); 879: // exists and name is *really* a "child" of path 880: if (exists(cname) && strncmp(cpath, cname, strlen(cpath)) == 0) 881: { 882: free(cpath); 883: char *p = mem.strdup(cname); 884: free(cname); 885: return p; 886: } 887: cont: 888: if (cpath) 889: free(cpath); 890: if (cname) 891: free(cname); 892: } 893: } 894: return NULL; 895: #else 896: assert(0); 897: #endif 898: } 899: 900: 901: int FileName::exists(const char *name) 902: { 903: #if POSIX 904: struct stat st; 905: 906: if (stat(name, &st) < 0) 907: return 0; 908: if (S_ISDIR(st.st_mode)) 909: return 2; 910: return 1; 911: #elif _WIN32 912: DWORD dw; 913: int result; 914: 915: dw = GetFileAttributesA(name); 916: if (dw == -1L) 917: result = 0; 918: else if (dw & FILE_ATTRIBUTE_DIRECTORY) 919: result = 2; 920: else 921: result = 1; 922: return result; 923: #else 924: assert(0); 925: #endif 926: } 927: 928: void FileName::ensurePathExists(const char *path) 929: { 930: //printf("FileName::ensurePathExists(%s)\n", path ? path : ""); 931: if (path && *path) 932: { 933: if (!exists(path)) 934: { 935: char *p = FileName::path(path); 936: if (*p) 937: { 938: #if _WIN32 939: size_t len = strlen(path); 940: if (len > 2 && p[-1] == ':' && path + 2 == p) 941: { mem.free(p); 942: return; 943: } 944: #endif 945: ensurePathExists(p); 946: mem.free(p); 947: } 948: #if _WIN32 949: if (path[strlen(path) - 1] != '\\') 950: #endif 951: #if POSIX 952: if (path[strlen(path) - 1] != '\\') 953: #endif 954: { 955: //printf("mkdir(%s)\n", path); 956: #if _WIN32 957: if (mkdir(path))
warning C4996: 'mkdir': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _mkdir. See online help for details. c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\direct.h(124) : see declaration of 'mkdir'
958: #endif 959: #if POSIX 960: if (mkdir(path, 0777)) 961: #endif 962: { 963: /* Don't error out if another instance of dmd just created 964: * this directory 965: */ 966: if (errno != EEXIST) 967: error("cannot create directory %s", path); 968: } 969: } 970: } 971: } 972: } 973: 974: 975: /****************************************** 976: * Return canonical version of name in a malloc'd buffer. 977: * This code is high risk. 978: */ 979: char *FileName::canonicalName(const char *name) 980: { 981: #if linux 982: // Lovely glibc extension to do it for us 983: return canonicalize_file_name(name); 984: #elif POSIX 985: #if _POSIX_VERSION >= 200809L || defined (linux) 986: // NULL destination buffer is allowed and preferred 987: return realpath(name, NULL); 988: #else 989: char *cname = NULL; 990: #if PATH_MAX 991: /* PATH_MAX must be defined as a constant in <limits.h>, 992: * otherwise using it is unsafe due to TOCTOU 993: */ 994: size_t path_max = (size_t)PATH_MAX; 995: if (path_max > 0) 996: { 997: /* Need to add one to PATH_MAX because of realpath() buffer overflow bug: 998: * http://isec.pl/vulnerabilities/isec-0011-wu-ftpd.txt 999: */ 1000: cname = (char *)malloc(path_max + 1); 1001: if (cname == NULL) 1002: return NULL; 1003: } 1004: #endif 1005: return realpath(name, cname); 1006: #endif 1007: #elif _WIN32 1008: /* Apparently, there is no good way to do this on Windows. 1009: * GetFullPathName isn't it. 1010: */ 1011: assert(0); 1012: return NULL; 1013: #else 1014: assert(0); 1015: return NULL; 1016: #endif 1017: } 1018: 1019: 1020: /****************************** File ********************************/ 1021: 1022: File::File(FileName *n) 1023: { 1024: ref = 0; 1025: buffer = NULL; 1026: len = 0; 1027: touchtime = NULL; 1028: name = n; 1029: } 1030: 1031: File::File(char *n) 1032: { 1033: ref = 0; 1034: buffer = NULL; 1035: len = 0; 1036: touchtime = NULL; 1037: name = new FileName(n, 0); 1038: } 1039: 1040: File::~File() 1041: { 1042: if (buffer) 1043: { 1044: if (ref == 0) 1045: mem.free(buffer); 1046: #if _WIN32 1047: else if (ref == 2) 1048: UnmapViewOfFile(buffer); 1049: #endif 1050: } 1051: if (touchtime) 1052: mem.free(touchtime); 1053: } 1054: 1055: void File::mark() 1056: { 1057: mem.mark(buffer); 1058: mem.mark(touchtime); 1059: mem.mark(name); 1060: } 1061: 1062: /************************************* 1063: */ 1064: 1065: int File::read() 1066: { 1067: #if POSIX 1068: off_t size; 1069: ssize_t numread; 1070: int fd; 1071: struct stat buf; 1072: int result = 0; 1073: char *name; 1074: 1075: name = this->name->toChars(); 1076: //printf("File::read('%s')\n",name); 1077: fd = open(name, O_RDONLY); 1078: if (fd == -1) 1079: { 1080: //printf("\topen error, errno = %d\n",errno); 1081: goto err1; 1082: } 1083: 1084: if (!ref) 1085: mem.free(buffer); 1086: ref = 0; // we own the buffer now 1087: 1088: //printf("\tfile opened\n"); 1089: if (fstat(fd, &buf)) 1090: { 1091: printf("\tfstat error, errno = %d\n",errno); 1092: goto err2; 1093: } 1094: size = buf.st_size; 1095: buffer = (unsigned char *) mem.malloc(size + 2); 1096: if (!buffer) 1097: { 1098: printf("\tmalloc error, errno = %d\n",errno); 1099: goto err2; 1100: } 1101: 1102: numread = ::read(fd, buffer, size); 1103: if (numread != size) 1104: { 1105: printf("\tread error, errno = %d\n",errno); 1106: goto err2; 1107: } 1108: 1109: if (touchtime) 1110: memcpy(touchtime, &buf, sizeof(buf)); 1111: 1112: if (close(fd) == -1) 1113: { 1114: printf("\tclose error, errno = %d\n",errno); 1115: goto err; 1116: } 1117: 1118: len = size; 1119: 1120: // Always store a wchar ^Z past end of buffer so scanner has a sentinel 1121: buffer[size] = 0; // ^Z is obsolete, use 0 1122: buffer[size + 1] = 0; 1123: return 0; 1124: 1125: err2: 1126: close(fd); 1127: err: 1128: mem.free(buffer); 1129: buffer = NULL; 1130: len = 0; 1131: 1132: err1: 1133: result = 1; 1134: return result; 1135: #elif _WIN32 1136: DWORD size; 1137: DWORD numread; 1138: HANDLE h; 1139: int result = 0; 1140: char *name; 1141: 1142: name = this->name->toChars(); 1143: h = CreateFileA(name,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING, 1144: FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,0); 1145: if (h == INVALID_HANDLE_VALUE) 1146: goto err1; 1147: 1148: if (!ref) 1149: mem.free(buffer); 1150: ref = 0; 1151: 1152: size = GetFileSize(h,NULL); 1153: buffer = (unsigned char *) mem.malloc(size + 2); 1154: if (!buffer) 1155: goto err2; 1156: 1157: if (ReadFile(h,buffer,size,&numread,NULL) != TRUE) 1158: goto err2; 1159: 1160: if (numread != size) 1161: goto err2; 1162: 1163: if (touchtime) 1164: { 1165: if (!GetFileTime(h, NULL, NULL, &((WIN32_FIND_DATAA *)touchtime)->ftLastWriteTime)) 1166: goto err2; 1167: } 1168: 1169: if (!CloseHandle(h)) 1170: goto err; 1171: 1172: len = size; 1173: 1174: // Always store a wchar ^Z past end of buffer so scanner has a sentinel 1175: buffer[size] = 0; // ^Z is obsolete, use 0 1176: buffer[size + 1] = 0; 1177: return 0; 1178: 1179: err2: 1180: CloseHandle(h); 1181: err: 1182: mem.free(buffer); 1183: buffer = NULL; 1184: len = 0; 1185: 1186: err1: 1187: result = 1; 1188: return result; 1189: #else 1190: assert(0); 1191: #endif 1192: } 1193: 1194: /***************************** 1195: * Read a file with memory mapped file I/O. 1196: */ 1197: 1198: int File::mmread() 1199: { 1200: #if POSIX 1201: return read(); 1202: #elif _WIN32 1203: HANDLE hFile; 1204: HANDLE hFileMap; 1205: DWORD size; 1206: char *name; 1207: 1208: name = this->name->toChars(); 1209: hFile = CreateFile(name, GENERIC_READ, 1210: FILE_SHARE_READ, NULL, 1211: OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 1212: if (hFile == INVALID_HANDLE_VALUE) 1213: goto Lerr; 1214: size = GetFileSize(hFile, NULL); 1215: //printf(" file created, size %d\n", size); 1216: 1217: hFileMap = CreateFileMapping(hFile,NULL,PAGE_READONLY,0,size,NULL); 1218: if (CloseHandle(hFile) != TRUE) 1219: goto Lerr; 1220: 1221: if (hFileMap == NULL) 1222: goto Lerr; 1223: 1224: //printf(" mapping created\n"); 1225: 1226: if (!ref) 1227: mem.free(buffer); 1228: ref = 2; 1229: buffer = (unsigned char *)MapViewOfFileEx(hFileMap, FILE_MAP_READ,0,0,size,NULL); 1230: if (CloseHandle(hFileMap) != TRUE) 1231: goto Lerr; 1232: if (buffer == NULL) // mapping view failed 1233: goto Lerr; 1234: 1235: len = size; 1236: //printf(" buffer = %p\n", buffer); 1237: 1238: return 0; 1239: 1240: Lerr: 1241: return GetLastError(); // failure 1242: #else 1243: assert(0); 1244: #endif 1245: } 1246: 1247: /********************************************* 1248: * Write a file. 1249: * Returns: 1250: * 0 success 1251: */ 1252: 1253: int File::write() 1254: { 1255: #if POSIX 1256: int fd; 1257: ssize_t numwritten; 1258: char *name; 1259: 1260: name = this->name->toChars(); 1261: fd = open(name, O_CREAT | O_WRONLY | O_TRUNC, 0644); 1262: if (fd == -1) 1263: goto err; 1264: 1265: numwritten = ::write(fd, buffer, len); 1266: if (len != numwritten) 1267: goto err2; 1268: 1269: if (close(fd) == -1) 1270: goto err; 1271: 1272: if (touchtime) 1273: { struct utimbuf ubuf; 1274: 1275: ubuf.actime = ((struct stat *)touchtime)->st_atime; 1276: ubuf.modtime = ((struct stat *)touchtime)->st_mtime; 1277: if (utime(name, &ubuf)) 1278: goto err; 1279: } 1280: return 0; 1281: 1282: err2: 1283: close(fd); 1284: ::remove(name); 1285: err: 1286: return 1; 1287: #elif _WIN32 1288: HANDLE h; 1289: DWORD numwritten; 1290: char *name; 1291: 1292: name = this->name->toChars(); 1293: h = CreateFileA(name,GENERIC_WRITE,0,NULL,CREATE_ALWAYS, 1294: FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,NULL); 1295: if (h == INVALID_HANDLE_VALUE) 1296: goto err; 1297: 1298: if (WriteFile(h,buffer,len,&numwritten,NULL) != TRUE) 1299: goto err2; 1300: 1301: if (len != numwritten) 1302: goto err2; 1303: 1304: if (touchtime) { 1305: SetFileTime(h, NULL, NULL, &((WIN32_FIND_DATAA *)touchtime)->ftLastWriteTime); 1306: } 1307: if (!CloseHandle(h)) 1308: goto err; 1309: return 0; 1310: 1311: err2: 1312: CloseHandle(h); 1313: DeleteFileA(name); 1314: err: 1315: return 1; 1316: #else 1317: assert(0); 1318: #endif 1319: } 1320: 1321: /********************************************* 1322: * Append to a file. 1323: * Returns: 1324: * 0 success 1325: */ 1326: 1327: int File::append() 1328: { 1329: #if POSIX 1330: return 1; 1331: #elif _WIN32 1332: HANDLE h; 1333: DWORD numwritten; 1334: char *name; 1335: 1336: name = this->name->toChars(); 1337: h = CreateFileA(name,GENERIC_WRITE,0,NULL,OPEN_ALWAYS, 1338: FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,NULL); 1339: if (h == INVALID_HANDLE_VALUE) 1340: goto err; 1341: 1342: #if 1 1343: SetFilePointer(h, 0, NULL, FILE_END); 1344: #else // INVALID_SET_FILE_POINTER doesn't seem to have a definition 1345: if (SetFilePointer(h, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER) 1346: goto err; 1347: #endif 1348: 1349: if (WriteFile(h,buffer,len,&numwritten,NULL) != TRUE) 1350: goto err2; 1351: 1352: if (len != numwritten) 1353: goto err2; 1354: 1355: if (touchtime) { 1356: SetFileTime(h, NULL, NULL, &((WIN32_FIND_DATAA *)touchtime)->ftLastWriteTime); 1357: } 1358: if (!CloseHandle(h)) 1359: goto err; 1360: return 0; 1361: 1362: err2: 1363: CloseHandle(h); 1364: err: 1365: return 1; 1366: #else 1367: assert(0); 1368: #endif 1369: } 1370: 1371: /************************************** 1372: */ 1373: 1374: void File::readv() 1375: { 1376: if (read()) 1377: error("Error reading file '%s'\n",name->toChars()); 1378: } 1379: 1380: /************************************** 1381: */ 1382: 1383: void File::mmreadv() 1384: { 1385: if (mmread()) 1386: readv(); 1387: } 1388: 1389: void File::writev() 1390: { 1391: if (write()) 1392: error("Error writing file '%s'\n",name->toChars()); 1393: } 1394: 1395: void File::appendv() 1396: { 1397: if (write()) 1398: error("Error appending to file '%s'\n",name->toChars()); 1399: } 1400: 1401: /******************************************* 1402: * Return !=0 if file exists. 1403: * 0: file doesn't exist 1404: * 1: normal file 1405: * 2: directory 1406: */ 1407: 1408: int File::exists() 1409: { 1410: #if POSIX 1411: return 0; 1412: #elif _WIN32 1413: DWORD dw; 1414: int result; 1415: char *name; 1416: 1417: name = this->name->toChars(); 1418: if (touchtime) 1419: dw = ((WIN32_FIND_DATAA *)touchtime)->dwFileAttributes; 1420: else 1421: dw = GetFileAttributesA(name); 1422: if (dw == -1L) 1423: result = 0; 1424: else if (dw & FILE_ATTRIBUTE_DIRECTORY) 1425: result = 2; 1426: else 1427: result = 1; 1428: return result; 1429: #else 1430: assert(0); 1431: #endif 1432: } 1433: 1434: void File::remove() 1435: { 1436: #if POSIX 1437: ::remove(this->name->toChars()); 1438: #elif _WIN32 1439: DeleteFileA(this->name->toChars()); 1440: #else 1441: assert(0); 1442: #endif 1443: } 1444: 1445: Files *File::match(char *n) 1446: { 1447: return match(new FileName(n, 0)); 1448: } 1449: 1450: Files *File::match(FileName *n) 1451: { 1452: #if POSIX 1453: return NULL; 1454: #elif _WIN32 1455: HANDLE h; 1456: WIN32_FIND_DATAA fileinfo; 1457: Files *a; 1458: char *c; 1459: char *name; 1460: 1461: a = new Files();
warning C6211: Leaking memory 'a' due to an exception. Consider using a local catch block to clean up memory: Lines: 1455, 1456, 1457, 1458, 1459, 1461, 1462, 1463, 1464, 1465, 1470, 1471, 1473, 1474, 1475, 1476
warning C6211: Leaking memory 'return value' due to an exception. Consider using a local catch block to clean up memory: Lines: 1455, 1456, 1457, 1458, 1459, 1461, 1462, 1463, 1464, 1465, 1470, 1471, 1473, 1474, 1475, 1476, 1477, 1478, 1479, 1480, 1470, 1471, 1473, 1474, 1475, 1476
1462: c = n->toChars(); 1463: name = n->name(); 1464: h = FindFirstFileA(c,&fileinfo); 1465: if (h != INVALID_HANDLE_VALUE) 1466: { 1467: do 1468: { 1469: // Glue path together with name 1470: char *fn; 1471: File *f; 1472: 1473: fn = (char *)mem.malloc(name - c + strlen(fileinfo.cFileName) + 1); 1474: memcpy(fn, c, name - c); 1475: strcpy(fn + (name - c), fileinfo.cFileName);
warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(105) : see declaration of 'strcpy'
1476: f = new File(fn); 1477: f->touchtime = mem.malloc(sizeof(WIN32_FIND_DATAA)); 1478: memcpy(f->touchtime, &fileinfo, sizeof(fileinfo)); 1479: a->push(f); 1480: } while (FindNextFileA(h,&fileinfo) != FALSE); 1481: FindClose(h); 1482: } 1483: return a; 1484: #else 1485: assert(0); 1486: #endif 1487: } 1488: 1489: int File::compareTime(File *f) 1490: { 1491: #if POSIX 1492: return 0; 1493: #elif _WIN32 1494: if (!touchtime) 1495: stat(); 1496: if (!f->touchtime) 1497: f->stat(); 1498: return CompareFileTime(&((WIN32_FIND_DATAA *)touchtime)->ftLastWriteTime, &((WIN32_FIND_DATAA *)f->touchtime)->ftLastWriteTime);
warning C6011: Dereferencing NULL pointer 'f->touchtime': Lines: 1494, 1495, 1496, 1497, 1498
1499: #else 1500: assert(0); 1501: #endif 1502: } 1503: 1504: void File::stat() 1505: { 1506: #if POSIX 1507: if (!touchtime) 1508: { 1509: touchtime = mem.calloc(1, sizeof(struct stat)); 1510: } 1511: #elif _WIN32 1512: HANDLE h; 1513: 1514: if (!touchtime) 1515: { 1516: touchtime = mem.calloc(1, sizeof(WIN32_FIND_DATAA)); 1517: } 1518: h = FindFirstFileA(name->toChars(),(WIN32_FIND_DATAA *)touchtime); 1519: if (h != INVALID_HANDLE_VALUE) 1520: { 1521: FindClose(h); 1522: } 1523: #else 1524: assert(0); 1525: #endif 1526: } 1527: 1528: void File::checkoffset(size_t offset, size_t nbytes) 1529: { 1530: if (offset > len || offset + nbytes > len) 1531: error("Corrupt file '%s': offset x%zx off end of file",toChars(),offset); 1532: } 1533: 1534: char *File::toChars() 1535: { 1536: return name->toChars(); 1537: } 1538: 1539: 1540: /************************* OutBuffer *************************/ 1541: 1542: OutBuffer::OutBuffer() 1543: { 1544: data = NULL; 1545: offset = 0; 1546: size = 0; 1547: } 1548: 1549: OutBuffer::~OutBuffer() 1550: { 1551: mem.free(data); 1552: } 1553: 1554: char *OutBuffer::extractData() 1555: { 1556: char *p; 1557: 1558: p = (char *)data; 1559: data = NULL; 1560: offset = 0; 1561: size = 0; 1562: return p; 1563: } 1564: 1565: void OutBuffer::mark() 1566: { 1567: mem.mark(data); 1568: } 1569: 1570: void OutBuffer::reserve(unsigned nbytes) 1571: { 1572: //printf("OutBuffer::reserve: size = %d, offset = %d, nbytes = %d\n", size, offset, nbytes); 1573: if (size - offset < nbytes) 1574: { 1575: size = (offset + nbytes) * 2; 1576: data = (unsigned char *)mem.realloc(data, size); 1577: } 1578: } 1579: 1580: void OutBuffer::reset() 1581: { 1582: offset = 0; 1583: } 1584: 1585: void OutBuffer::setsize(unsigned size) 1586: { 1587: offset = size; 1588: } 1589: 1590: void OutBuffer::write(const void *data, unsigned nbytes) 1591: { 1592: reserve(nbytes); 1593: memcpy(this->data + offset, data, nbytes); 1594: offset += nbytes; 1595: } 1596: 1597: void OutBuffer::writebstring(unsigned char *string) 1598: { 1599: write(string,*string + 1); 1600: } 1601: 1602: void OutBuffer::writestring(const char *string) 1603: { 1604: write(string,strlen(string)); 1605: } 1606: 1607: void OutBuffer::writedstring(const char *string) 1608: { 1609: #if M_UNICODE 1610: for (; *string; string++) 1611: { 1612: writedchar(*string); 1613: } 1614: #else 1615: write(string,strlen(string)); 1616: #endif 1617: } 1618: 1619: void OutBuffer::writedstring(const wchar_t *string) 1620: { 1621: #if M_UNICODE 1622: write(string,wcslen(string) * sizeof(wchar_t)); 1623: #else 1624: for (; *string; string++) 1625: { 1626: writedchar(*string); 1627: } 1628: #endif 1629: } 1630: 1631: void OutBuffer::prependstring(const char *string) 1632: { unsigned len; 1633: 1634: len = strlen(string); 1635: reserve(len); 1636: memmove(data + len, data, offset); 1637: memcpy(data, string, len); 1638: offset += len; 1639: } 1640: 1641: void OutBuffer::writenl() 1642: { 1643: #if _WIN32 1644: #if M_UNICODE 1645: write4(0x000A000D); // newline is CR,LF on Microsoft OS's 1646: #else 1647: writeword(0x0A0D); // newline is CR,LF on Microsoft OS's 1648: #endif 1649: #else 1650: #if M_UNICODE 1651: writeword('\n'); 1652: #else 1653: writeByte('\n'); 1654: #endif 1655: #endif 1656: } 1657: 1658: void OutBuffer::writeByte(unsigned b) 1659: { 1660: reserve(1); 1661: this->data[offset] = (unsigned char)b; 1662: offset++; 1663: } 1664: 1665: void OutBuffer::writeUTF8(unsigned b) 1666: { 1667: reserve(6); 1668: if (b <= 0x7F) 1669: { 1670: this->data[offset] = (unsigned char)b; 1671: offset++; 1672: } 1673: else if (b <= 0x7FF) 1674: { 1675: this->data[offset + 0] = (unsigned char)((b >> 6) | 0xC0); 1676: this->data[offset + 1] = (unsigned char)((b & 0x3F) | 0x80); 1677: offset += 2; 1678: } 1679: else if (b <= 0xFFFF) 1680: { 1681: this->data[offset + 0] = (unsigned char)((b >> 12) | 0xE0); 1682: this->data[offset + 1] = (unsigned char)(((b >> 6) & 0x3F) | 0x80); 1683: this->data[offset + 2] = (unsigned char)((b & 0x3F) | 0x80); 1684: offset += 3; 1685: } 1686: else if (b <= 0x1FFFFF) 1687: { 1688: this->data[offset + 0] = (unsigned char)((b >> 18) | 0xF0); 1689: this->data[offset + 1] = (unsigned char)(((b >> 12) & 0x3F) | 0x80); 1690: this->data[offset + 2] = (unsigned char)(((b >> 6) & 0x3F) | 0x80); 1691: this->data[offset + 3] = (unsigned char)((b & 0x3F) | 0x80); 1692: offset += 4; 1693: } 1694: else if (b <= 0x3FFFFFF) 1695: { 1696: this->data[offset + 0] = (unsigned char)((b >> 24) | 0xF8); 1697: this->data[offset + 1] = (unsigned char)(((b >> 18) & 0x3F) | 0x80); 1698: this->data[offset + 2] = (unsigned char)(((b >> 12) & 0x3F) | 0x80); 1699: this->data[offset + 3] = (unsigned char)(((b >> 6) & 0x3F) | 0x80); 1700: this->data[offset + 4] = (unsigned char)((b & 0x3F) | 0x80); 1701: offset += 5; 1702: } 1703: else if (b <= 0x7FFFFFFF) 1704: { 1705: this->data[offset + 0] = (unsigned char)((b >> 30) | 0xFC); 1706: this->data[offset + 1] = (unsigned char)(((b >> 24) & 0x3F) | 0x80); 1707: this->data[offset + 2] = (unsigned char)(((b >> 18) & 0x3F) | 0x80); 1708: this->data[offset + 3] = (unsigned char)(((b >> 12) & 0x3F) | 0x80); 1709: this->data[offset + 4] = (unsigned char)(((b >> 6) & 0x3F) | 0x80); 1710: this->data[offset + 5] = (unsigned char)((b & 0x3F) | 0x80); 1711: offset += 6; 1712: } 1713: else 1714: assert(0); 1715: } 1716: 1717: void OutBuffer::writedchar(unsigned b) 1718: { 1719: reserve(Dchar_mbmax * sizeof(dchar)); 1720: offset = (unsigned char *)Dchar::put((dchar *)(this->data + offset), (dchar)b) - 1721: this->data; 1722: } 1723: 1724: void OutBuffer::prependbyte(unsigned b) 1725: { 1726: reserve(1); 1727: memmove(data + 1, data, offset); 1728: data[0] = (unsigned char)b; 1729: offset++; 1730: } 1731: 1732: void OutBuffer::writeword(unsigned w) 1733: { 1734: reserve(2); 1735: *(unsigned short *)(this->data + offset) = (unsigned short)w; 1736: offset += 2; 1737: } 1738: 1739: void OutBuffer::writeUTF16(unsigned w) 1740: { 1741: reserve(4); 1742: if (w <= 0xFFFF) 1743: { 1744: *(unsigned short *)(this->data + offset) = (unsigned short)w; 1745: offset += 2; 1746: } 1747: else if (w <= 0x10FFFF) 1748: { 1749: *(unsigned short *)(this->data + offset) = (unsigned short)((w >> 10) + 0xD7C0); 1750: *(unsigned short *)(this->data + offset + 2) = (unsigned short)((w & 0x3FF) | 0xDC00); 1751: offset += 4; 1752: } 1753: else 1754: assert(0); 1755: } 1756: 1757: void OutBuffer::write4(unsigned w) 1758: { 1759: reserve(4); 1760: *(unsigned *)(this->data + offset) = w; 1761: offset += 4; 1762: } 1763: 1764: void OutBuffer::write(OutBuffer *buf) 1765: { 1766: if (buf) 1767: { reserve(buf->offset); 1768: memcpy(data + offset, buf->data, buf->offset); 1769: offset += buf->offset; 1770: } 1771: } 1772: 1773: void OutBuffer::write(Object *obj) 1774: { 1775: if (obj) 1776: { 1777: writestring(obj->toChars()); 1778: } 1779: } 1780: 1781: void OutBuffer::fill0(unsigned nbytes) 1782: { 1783: reserve(nbytes); 1784: memset(data + offset,0,nbytes); 1785: offset += nbytes; 1786: } 1787: 1788: void OutBuffer::align(unsigned size) 1789: { unsigned nbytes; 1790: 1791: nbytes = ((offset + size - 1) & ~(size - 1)) - offset; 1792: fill0(nbytes); 1793: } 1794: 1795: 1796: //////////////////////////////////////////////////////////////// 1797: // The compiler shipped with Visual Studio 2005 (and possible 1798: // other versions) does not support C99 printf format specfiers 1799: // such as %z and %j 1800: #if _MSC_VER 1801: using std::string; 1802: using std::wstring; 1803: 1804: template<typename S> 1805: inline void 1806: search_and_replace(S& str, const S& what, const S& replacement) 1807: { 1808: assert(!what.empty()); 1809: size_t pos = str.find(what); 1810: while (pos != S::npos) 1811: { 1812: str.replace(pos, what.size(), replacement); 1813: pos = str.find(what, pos + replacement.size()); 1814: } 1815: } 1816: #define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f) \ 1817: S tmp = f; \ 1818: search_and_replace(fmt, S("%z"), S("%l")); \ 1819: search_and_replace(fmt, S("%j"), S("%i")); \ 1820: f = tmp.c_str(); 1821: #else 1822: #define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f) 1823: #endif 1824: 1825: void OutBuffer::vprintf(const char *format, va_list args) 1826: { 1827: char buffer[128]; 1828: char *p; 1829: unsigned psize; 1830: int count; 1831: 1832: WORKAROUND_C99_SPECIFIERS_BUG(string, fmt, format); 1833: 1834: p = buffer; 1835: psize = sizeof(buffer); 1836: for (;;) 1837: { 1838: #if _WIN32 1839: count = _vsnprintf(p,psize,format,args);
warning C4996: '_vsnprintf': This function or variable may be unsafe. Consider using _vsnprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(363) : see declaration of '_vsnprintf'
1840: if (count != -1) 1841: break; 1842: psize *= 2; 1843: #elif POSIX 1844: va_list va; 1845: va_copy(va, args); 1846: /* 1847: The functions vprintf(), vfprintf(), vsprintf(), vsnprintf() 1848: are equivalent to the functions printf(), fprintf(), sprintf(), 1849: snprintf(), respectively, except that they are called with a 1850: va_list instead of a variable number of arguments. These 1851: functions do not call the va_end macro. Consequently, the value 1852: of ap is undefined after the call. The application should call 1853: va_end(ap) itself afterwards. 1854: */ 1855: count = vsnprintf(p,psize,format,va); 1856: va_end(va); 1857: if (count == -1) 1858: psize *= 2; 1859: else if (count >= psize) 1860: psize = count + 1; 1861: else 1862: break; 1863: #else 1864: assert(0); 1865: #endif 1866: p = (char *) alloca(psize); // buffer too small, try again with larger size
warning C6255: _alloca indicates failure by raising a stack overflow exception. Consider using _malloca instead
warning C6263: Using _alloca in a loop: this can quickly overflow stack: Lines: 1836
1867: } 1868: write(p,count); 1869: } 1870: 1871: #if M_UNICODE 1872: void OutBuffer::vprintf(const wchar_t *format, va_list args) 1873: { 1874: dchar buffer[128]; 1875: dchar *p; 1876: unsigned psize; 1877: int count; 1878: 1879: WORKAROUND_C99_SPECIFIERS_BUG(wstring, fmt, format); 1880: 1881: p = buffer; 1882: psize = sizeof(buffer) / sizeof(buffer[0]); 1883: for (;;) 1884: { 1885: #if _WIN32 1886: count = _vsnwprintf(p,psize,format,args); 1887: if (count != -1) 1888: break; 1889: psize *= 2; 1890: #elif POSIX 1891: va_list va; 1892: va_copy(va, args); 1893: count = vsnwprintf(p,psize,format,va); 1894: va_end(va); 1895: 1896: if (count == -1) 1897: psize *= 2; 1898: else if (count >= psize) 1899: psize = count + 1; 1900: else 1901: break; 1902: #else 1903: assert(0); 1904: #endif 1905: p = (dchar *) alloca(psize * 2); // buffer too small, try again with larger size 1906: } 1907: write(p,count * 2); 1908: } 1909: #endif 1910: 1911: void OutBuffer::printf(const char *format, ...) 1912: { 1913: va_list ap; 1914: va_start(ap, format); 1915: vprintf(format,ap); 1916: va_end(ap); 1917: } 1918: 1919: #if M_UNICODE 1920: void OutBuffer::printf(const wchar_t *format, ...) 1921: { 1922: va_list ap; 1923: va_start(ap, format); 1924: vprintf(format,ap); 1925: va_end(ap); 1926: } 1927: #endif 1928: 1929: void OutBuffer::bracket(char left, char right) 1930: { 1931: reserve(2); 1932: memmove(data + 1, data, offset); 1933: data[0] = left; 1934: data[offset + 1] = right; 1935: offset += 2; 1936: } 1937: 1938: /****************** 1939: * Insert left at i, and right at j. 1940: * Return index just past right. 1941: */ 1942: 1943: unsigned OutBuffer::bracket(unsigned i, const char *left, unsigned j, const char *right) 1944: { 1945: size_t leftlen = strlen(left); 1946: size_t rightlen = strlen(right); 1947: reserve(leftlen + rightlen); 1948: insert(i, left, leftlen); 1949: insert(j + leftlen, right, rightlen); 1950: return j + leftlen + rightlen; 1951: } 1952: 1953: void OutBuffer::spread(unsigned offset, unsigned nbytes) 1954: { 1955: reserve(nbytes); 1956: memmove(data + offset + nbytes, data + offset, 1957: this->offset - offset); 1958: this->offset += nbytes; 1959: } 1960: 1961: /**************************************** 1962: * Returns: offset + nbytes 1963: */ 1964: 1965: unsigned OutBuffer::insert(unsigned offset, const void *p, unsigned nbytes) 1966: { 1967: spread(offset, nbytes); 1968: memmove(data + offset, p, nbytes); 1969: return offset + nbytes; 1970: } 1971: 1972: void OutBuffer::remove(unsigned offset, unsigned nbytes) 1973: { 1974: memmove(data + offset, data + offset + nbytes, this->offset - (offset + nbytes)); 1975: this->offset -= nbytes; 1976: } 1977: 1978: char *OutBuffer::toChars() 1979: { 1980: writeByte(0); 1981: return (char *)data; 1982: } 1983: 1984: /********************************* Bits ****************************/ 1985: 1986: Bits::Bits() 1987: { 1988: data = NULL; 1989: bitdim = 0; 1990: allocdim = 0; 1991: } 1992: 1993: Bits::~Bits() 1994: { 1995: mem.free(data); 1996: } 1997: 1998: void Bits::mark() 1999: { 2000: mem.mark(data); 2001: } 2002: 2003: void Bits::resize(unsigned bitdim) 2004: { 2005: unsigned allocdim; 2006: unsigned mask; 2007: 2008: allocdim = (bitdim + 31) / 32; 2009: data = (unsigned *)mem.realloc(data, allocdim * sizeof(data[0])); 2010: if (this->allocdim < allocdim) 2011: memset(data + this->allocdim, 0, (allocdim - this->allocdim) * sizeof(data[0])); 2012: 2013: // Clear other bits in last word 2014: mask = (1 << (bitdim & 31)) - 1; 2015: if (mask) 2016: data[allocdim - 1] &= ~mask; 2017: 2018: this->bitdim = bitdim; 2019: this->allocdim = allocdim; 2020: } 2021: 2022: void Bits::set(unsigned bitnum) 2023: { 2024: data[bitnum / 32] |= 1 << (bitnum & 31); 2025: } 2026: 2027: void Bits::clear(unsigned bitnum) 2028: { 2029: data[bitnum / 32] &= ~(1 << (bitnum & 31)); 2030: } 2031: 2032: int Bits::test(unsigned bitnum) 2033: { 2034: return data[bitnum / 32] & (1 << (bitnum & 31)); 2035: } 2036: 2037: void Bits::set() 2038: { unsigned mask; 2039: 2040: memset(data, ~0, allocdim * sizeof(data[0])); 2041: 2042: // Clear other bits in last word 2043: mask = (1 << (bitdim & 31)) - 1; 2044: if (mask) 2045: data[allocdim - 1] &= mask; 2046: } 2047: 2048: void Bits::clear() 2049: { 2050: memset(data, 0, allocdim * sizeof(data[0])); 2051: } 2052: 2053: void Bits::copy(Bits *from) 2054: { 2055: assert(bitdim == from->bitdim); 2056: memcpy(data, from->data, allocdim * sizeof(data[0])); 2057: } 2058: 2059: Bits *Bits::clone() 2060: { 2061: Bits *b; 2062: 2063: b = new Bits(); 2064: b->resize(bitdim); 2065: b->copy(this); 2066: return b; 2067: } 2068: 2069: void Bits::sub(Bits *b) 2070: { 2071: unsigned u; 2072: 2073: for (u = 0; u < allocdim; u++) 2074: data[u] &= ~b->data[u]; 2075: } 2076: 2077: 2078: 2079: 2080: 2081: 2082: 2083: 2084: 2085: 2086: 2087: 2088: 2089: 2090: 2091: