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