annotate dmd/root/root.c @ 1194:1853dcd9b944

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