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