Mercurial > projects > ldc
annotate dmd/root.c @ 1138:4c8bb03e4fbc
Update DtoConstFP() to be correct after LLVM r67562, which changed the way the
APFloat constructor expects its i80 APInts to be formatted. (They're now
actually consistent with the x87 format)
author | Frits van Bommel <fvbommel wxs.nl> |
---|---|
date | Tue, 24 Mar 2009 15:24:59 +0100 |
parents | 0f8aeb31678c |
children | c271eca933fb |
rev | line source |
---|---|
336 | 1 |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
872
diff
changeset
|
2 // Copyright (c) 1999-2009 by Digital Mars |
336 | 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" | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
872
diff
changeset
|
43 #include "rmem.h" |
336 | 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 | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
872
diff
changeset
|
379 #if MACINTOSH |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
872
diff
changeset
|
380 case ',': |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
872
diff
changeset
|
381 #endif |
336 | 382 #if _WIN32 |
383 case ';': | |
384 #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
|
385 #if POSIX |
336 | 386 case ':': |
387 #endif | |
388 p++; | |
389 break; // note that ; cannot appear as part | |
390 // of a path, quotes won't protect it | |
391 | |
392 case 0x1A: // ^Z means end of file | |
393 case 0: | |
394 break; | |
395 | |
396 case '\r': | |
397 continue; // ignore carriage returns | |
398 | |
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
|
399 #if POSIX |
336 | 400 case '~': |
401 buf.writestring(getenv("HOME")); | |
402 continue; | |
403 #endif | |
404 | |
405 case ' ': | |
406 case '\t': // tabs in filenames? | |
407 if (!instring) // if not in string | |
408 break; // treat as end of path | |
409 default: | |
410 buf.writeByte(c); | |
411 continue; | |
412 } | |
413 break; | |
414 } | |
415 if (buf.offset) // if path is not empty | |
416 { | |
417 buf.writeByte(0); // to asciiz | |
418 array->push(buf.extractData()); | |
419 } | |
420 } while (c); | |
421 } | |
422 return array; | |
423 } | |
424 | |
425 hash_t FileName::hashCode() | |
426 { | |
427 #if _WIN32 | |
428 // We need a different hashCode because it must be case-insensitive | |
429 size_t len = strlen(str); | |
430 hash_t hash = 0; | |
431 unsigned char *s = (unsigned char *)str; | |
432 | |
433 for (;;) | |
434 { | |
435 switch (len) | |
436 { | |
437 case 0: | |
438 return hash; | |
439 | |
440 case 1: | |
441 hash *= 37; | |
442 hash += *(uint8_t *)s | 0x20; | |
443 return hash; | |
444 | |
445 case 2: | |
446 hash *= 37; | |
447 hash += *(uint16_t *)s | 0x2020; | |
448 return hash; | |
449 | |
450 case 3: | |
451 hash *= 37; | |
452 hash += ((*(uint16_t *)s << 8) + | |
453 ((uint8_t *)s)[2]) | 0x202020; | |
454 break; | |
455 | |
456 default: | |
457 hash *= 37; | |
458 hash += *(uint32_t *)s | 0x20202020; | |
459 s += 4; | |
460 len -= 4; | |
461 break; | |
462 } | |
463 } | |
464 #else | |
465 // darwin HFS is case insensitive, though... | |
466 return String::hashCode(); | |
467 #endif | |
468 } | |
469 | |
470 int FileName::compare(Object *obj) | |
471 { | |
472 #if _WIN32 | |
473 return stricmp(str,((FileName *)obj)->str); | |
474 #else | |
475 return String::compare(obj); | |
476 #endif | |
477 } | |
478 | |
479 int FileName::equals(Object *obj) | |
480 { | |
481 #if _WIN32 | |
482 return stricmp(str,((FileName *)obj)->str) == 0; | |
483 #else | |
484 return String::equals(obj); | |
485 #endif | |
486 } | |
487 | |
488 /************************************ | |
489 * Return !=0 if absolute path name. | |
490 */ | |
491 | |
492 int FileName::absolute(const char *name) | |
493 { | |
429
6bd99cc5eb08
Allow / as a path separator on Windows.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
494 return |
336 | 495 #if _WIN32 |
429
6bd99cc5eb08
Allow / as a path separator on Windows.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
496 (*name == '\\') || |
6bd99cc5eb08
Allow / as a path separator on Windows.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
497 (*name == '/') || |
6bd99cc5eb08
Allow / as a path separator on Windows.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
498 (*name && name[1] == ':') || |
336 | 499 #endif |
429
6bd99cc5eb08
Allow / as a path separator on Windows.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
500 (*name == '/'); |
336 | 501 } |
502 | |
503 /******************************** | |
504 * Return filename extension (read-only). | |
505 * Points past '.' of extension. | |
506 * If there isn't one, return NULL. | |
507 */ | |
508 | |
509 char *FileName::ext(const char *str) | |
510 { | |
511 char *e; | |
512 size_t len = strlen(str); | |
513 | |
514 e = (char *)str + len; | |
515 for (;;) | |
516 { | |
517 switch (*e) | |
518 { case '.': | |
519 return e + 1; | |
429
6bd99cc5eb08
Allow / as a path separator on Windows.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
520 |
336 | 521 case '/': |
522 break; | |
429
6bd99cc5eb08
Allow / as a path separator on Windows.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
523 |
336 | 524 #if _WIN32 |
525 case '\\': | |
526 case ':': | |
527 break; | |
528 #endif | |
529 default: | |
530 if (e == str) | |
531 break; | |
532 e--; | |
533 continue; | |
534 } | |
535 return NULL; | |
536 } | |
537 } | |
538 | |
539 char *FileName::ext() | |
540 { | |
541 return ext(str); | |
542 } | |
543 | |
544 /******************************** | |
545 * Return mem.malloc'd filename with extension removed. | |
546 */ | |
547 | |
548 char *FileName::removeExt(const char *str) | |
549 { | |
550 const char *e = ext(str); | |
551 if (e) | |
552 { size_t len = (e - str) - 1; | |
553 char *n = (char *)mem.malloc(len + 1); | |
554 memcpy(n, str, len); | |
555 n[len] = 0; | |
556 return n; | |
557 } | |
558 return mem.strdup(str); | |
559 } | |
560 | |
561 /******************************** | |
562 * Return filename name excluding path (read-only). | |
563 */ | |
564 | |
565 char *FileName::name(const char *str) | |
566 { | |
567 char *e; | |
568 size_t len = strlen(str); | |
569 | |
570 e = (char *)str + len; | |
571 for (;;) | |
572 { | |
573 switch (*e) | |
574 { | |
429
6bd99cc5eb08
Allow / as a path separator on Windows.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
575 |
336 | 576 case '/': |
577 return e + 1; | |
429
6bd99cc5eb08
Allow / as a path separator on Windows.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
578 |
336 | 579 #if _WIN32 |
580 case '\\': | |
581 case ':': | |
582 return e + 1; | |
583 #endif | |
584 default: | |
585 if (e == str) | |
586 break; | |
587 e--; | |
588 continue; | |
589 } | |
590 return e; | |
591 } | |
592 } | |
593 | |
594 char *FileName::name() | |
595 { | |
596 return name(str); | |
597 } | |
598 | |
599 /************************************** | |
600 * Return path portion of str. | |
601 * Path will does not include trailing path separator. | |
602 */ | |
603 | |
604 char *FileName::path(const char *str) | |
605 { | |
606 char *n = name(str); | |
607 char *path; | |
608 size_t pathlen; | |
609 | |
610 if (n > str) | |
611 { | |
429
6bd99cc5eb08
Allow / as a path separator on Windows.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
612 |
336 | 613 if (n[-1] == '/') |
614 n--; | |
429
6bd99cc5eb08
Allow / as a path separator on Windows.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
615 |
336 | 616 #if _WIN32 |
617 if (n[-1] == '\\') | |
618 n--; | |
619 #endif | |
620 } | |
621 pathlen = n - str; | |
622 path = (char *)mem.malloc(pathlen + 1); | |
623 memcpy(path, str, pathlen); | |
624 path[pathlen] = 0; | |
625 return path; | |
626 } | |
627 | |
628 /************************************** | |
629 * Replace filename portion of path. | |
630 */ | |
631 | |
632 char *FileName::replaceName(char *path, char *name) | |
633 { char *f; | |
634 char *n; | |
635 size_t pathlen; | |
636 size_t namelen; | |
637 | |
638 if (absolute(name)) | |
639 return name; | |
640 | |
641 n = FileName::name(path); | |
642 if (n == path) | |
643 return name; | |
644 pathlen = n - path; | |
645 namelen = strlen(name); | |
646 f = (char *)mem.malloc(pathlen + 1 + namelen + 1); | |
647 memcpy(f, path, pathlen); | |
429
6bd99cc5eb08
Allow / as a path separator on Windows.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
648 |
431
3dd9ae9ea708
Another fix to DMD's path code.
Christian Kamm <kamm incasoftware de>
parents:
430
diff
changeset
|
649 if ( |
3dd9ae9ea708
Another fix to DMD's path code.
Christian Kamm <kamm incasoftware de>
parents:
430
diff
changeset
|
650 path[pathlen - 1] != '/' |
3dd9ae9ea708
Another fix to DMD's path code.
Christian Kamm <kamm incasoftware de>
parents:
430
diff
changeset
|
651 #if _WIN32 |
3dd9ae9ea708
Another fix to DMD's path code.
Christian Kamm <kamm incasoftware de>
parents:
430
diff
changeset
|
652 && path[pathlen - 1] != '\\' && path[pathlen - 1] != ':' |
3dd9ae9ea708
Another fix to DMD's path code.
Christian Kamm <kamm incasoftware de>
parents:
430
diff
changeset
|
653 #endif |
3dd9ae9ea708
Another fix to DMD's path code.
Christian Kamm <kamm incasoftware de>
parents:
430
diff
changeset
|
654 ) |
336 | 655 { f[pathlen] = '/'; |
656 pathlen++; | |
657 } | |
429
6bd99cc5eb08
Allow / as a path separator on Windows.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
658 |
336 | 659 memcpy(f + pathlen, name, namelen + 1); |
660 return f; | |
661 } | |
662 | |
663 /*************************** | |
664 */ | |
665 | |
666 FileName *FileName::defaultExt(const char *name, const char *ext) | |
667 { | |
668 char *e; | |
669 char *s; | |
670 size_t len; | |
671 size_t extlen; | |
672 | |
673 e = FileName::ext(name); | |
674 if (e) // if already has an extension | |
675 return new FileName((char *)name, 0); | |
676 | |
677 len = strlen(name); | |
678 extlen = strlen(ext); | |
679 s = (char *)alloca(len + 1 + extlen + 1); | |
680 memcpy(s,name,len); | |
681 s[len] = '.'; | |
682 memcpy(s + len + 1, ext, extlen + 1); | |
683 return new FileName(s, 0); | |
684 } | |
685 | |
686 /*************************** | |
687 */ | |
688 | |
689 FileName *FileName::forceExt(const char *name, const char *ext) | |
690 { | |
691 char *e; | |
692 char *s; | |
693 size_t len; | |
694 size_t extlen; | |
695 | |
696 e = FileName::ext(name); | |
697 if (e) // if already has an extension | |
698 { | |
699 len = e - name; | |
700 extlen = strlen(ext); | |
701 | |
702 s = (char *)alloca(len + extlen + 1); | |
703 memcpy(s,name,len); | |
704 memcpy(s + len, ext, extlen + 1); | |
705 return new FileName(s, 0); | |
706 } | |
707 else | |
708 return defaultExt(name, ext); // doesn't have one | |
709 } | |
710 | |
711 /****************************** | |
712 * Return !=0 if extensions match. | |
713 */ | |
714 | |
715 int FileName::equalsExt(const char *ext) | |
716 { const char *e; | |
717 | |
718 e = FileName::ext(); | |
719 if (!e && !ext) | |
720 return 1; | |
721 if (!e || !ext) | |
722 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
|
723 #if POSIX |
336 | 724 return strcmp(e,ext) == 0; |
725 #endif | |
726 #if _WIN32 | |
727 return stricmp(e,ext) == 0; | |
728 #endif | |
729 } | |
730 | |
731 /************************************* | |
732 * Copy file from this to to. | |
733 */ | |
734 | |
735 void FileName::CopyTo(FileName *to) | |
736 { | |
737 File file(this); | |
738 | |
739 #if _WIN32 | |
740 file.touchtime = mem.malloc(sizeof(WIN32_FIND_DATAA)); // keep same file time | |
741 #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
|
742 #if POSIX |
336 | 743 file.touchtime = mem.malloc(sizeof(struct stat)); // keep same file time |
744 #endif | |
745 file.readv(); | |
746 file.name = to; | |
747 file.writev(); | |
748 } | |
749 | |
750 /************************************* | |
751 * Search Path for file. | |
752 * Input: | |
753 * cwd if !=0, search current directory before searching path | |
754 */ | |
755 | |
658
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
571
diff
changeset
|
756 char *FileName::searchPath(Array *path, const char *name, int cwd) |
336 | 757 { |
758 if (absolute(name)) | |
759 { | |
658
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
571
diff
changeset
|
760 return exists(name) ? (char *)name : NULL; |
336 | 761 } |
762 if (cwd) | |
763 { | |
764 if (exists(name)) | |
658
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
571
diff
changeset
|
765 return (char *)name; |
336 | 766 } |
767 if (path) | |
768 { unsigned i; | |
769 | |
770 for (i = 0; i < path->dim; i++) | |
771 { | |
772 char *p = (char *)path->data[i]; | |
773 char *n = combine(p, name); | |
774 | |
775 if (exists(n)) | |
776 return n; | |
777 } | |
778 } | |
779 return NULL; | |
780 } | |
781 | |
782 int FileName::exists(const char *name) | |
783 { | |
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
|
784 #if POSIX |
336 | 785 struct stat st; |
786 | |
787 if (stat(name, &st) < 0) | |
788 return 0; | |
789 if (S_ISDIR(st.st_mode)) | |
790 return 2; | |
791 return 1; | |
792 #endif | |
793 #if _WIN32 | |
794 DWORD dw; | |
795 int result; | |
796 | |
797 dw = GetFileAttributesA(name); | |
798 if (dw == -1L) | |
799 result = 0; | |
800 else if (dw & FILE_ATTRIBUTE_DIRECTORY) | |
801 result = 2; | |
802 else | |
803 result = 1; | |
804 return result; | |
805 #endif | |
806 } | |
807 | |
808 void FileName::ensurePathExists(const char *path) | |
809 { | |
810 //printf("FileName::ensurePathExists(%s)\n", path ? path : ""); | |
811 if (path && *path) | |
812 { | |
813 if (!exists(path)) | |
814 { | |
815 char *p = FileName::path(path); | |
816 if (*p) | |
817 { | |
818 #if _WIN32 | |
819 size_t len = strlen(p); | |
820 if (len > 2 && p[-1] == ':') | |
821 { mem.free(p); | |
822 return; | |
823 } | |
824 #endif | |
825 ensurePathExists(p); | |
826 mem.free(p); | |
827 } | |
828 #if _WIN32 | |
829 if (path[strlen(path) - 1] != '\\') | |
830 #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
|
831 #if POSIX |
336 | 832 if (path[strlen(path) - 1] != '\\') |
833 #endif | |
834 { | |
835 //printf("mkdir(%s)\n", path); | |
836 #if _WIN32 | |
837 if (mkdir(path)) | |
838 #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
|
839 #if POSIX |
336 | 840 if (mkdir(path, 0777)) |
841 #endif | |
842 error("cannot create directory %s", path); | |
843 } | |
844 } | |
845 } | |
846 } | |
847 | |
848 /****************************** File ********************************/ | |
849 | |
850 File::File(FileName *n) | |
851 { | |
852 ref = 0; | |
853 buffer = NULL; | |
854 len = 0; | |
855 touchtime = NULL; | |
856 name = n; | |
857 } | |
858 | |
859 File::File(char *n) | |
860 { | |
861 ref = 0; | |
862 buffer = NULL; | |
863 len = 0; | |
864 touchtime = NULL; | |
865 name = new FileName(n, 0); | |
866 } | |
867 | |
868 File::~File() | |
869 { | |
870 if (buffer) | |
871 { | |
872 if (ref == 0) | |
873 mem.free(buffer); | |
874 #if _WIN32 | |
875 else if (ref == 2) | |
876 UnmapViewOfFile(buffer); | |
877 #endif | |
878 } | |
879 if (touchtime) | |
880 mem.free(touchtime); | |
881 } | |
882 | |
883 void File::mark() | |
884 { | |
885 mem.mark(buffer); | |
886 mem.mark(touchtime); | |
887 mem.mark(name); | |
888 } | |
889 | |
890 /************************************* | |
891 */ | |
892 | |
893 int File::read() | |
894 { | |
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
|
895 #if POSIX |
336 | 896 off_t size; |
897 ssize_t numread; | |
898 int fd; | |
899 struct stat buf; | |
900 int result = 0; | |
901 char *name; | |
902 | |
903 name = this->name->toChars(); | |
904 //printf("File::read('%s')\n",name); | |
905 fd = open(name, O_RDONLY); | |
906 if (fd == -1) | |
907 { result = errno; | |
908 //printf("\topen error, errno = %d\n",errno); | |
909 goto err1; | |
910 } | |
911 | |
912 if (!ref) | |
913 mem.free(buffer); | |
914 ref = 0; // we own the buffer now | |
915 | |
916 //printf("\tfile opened\n"); | |
917 if (fstat(fd, &buf)) | |
918 { | |
919 printf("\tfstat error, errno = %d\n",errno); | |
920 goto err2; | |
921 } | |
922 size = buf.st_size; | |
923 buffer = (unsigned char *) mem.malloc(size + 2); | |
924 if (!buffer) | |
925 { | |
926 printf("\tmalloc error, errno = %d\n",errno); | |
927 goto err2; | |
928 } | |
929 | |
930 numread = ::read(fd, buffer, size); | |
931 if (numread != size) | |
932 { | |
933 printf("\tread error, errno = %d\n",errno); | |
934 goto err2; | |
935 } | |
936 | |
937 if (touchtime) | |
938 memcpy(touchtime, &buf, sizeof(buf)); | |
939 | |
940 if (close(fd) == -1) | |
941 { | |
942 printf("\tclose error, errno = %d\n",errno); | |
943 goto err; | |
944 } | |
945 | |
946 len = size; | |
947 | |
948 // Always store a wchar ^Z past end of buffer so scanner has a sentinel | |
949 buffer[size] = 0; // ^Z is obsolete, use 0 | |
950 buffer[size + 1] = 0; | |
951 return 0; | |
952 | |
953 err2: | |
954 close(fd); | |
955 err: | |
956 mem.free(buffer); | |
957 buffer = NULL; | |
958 len = 0; | |
959 | |
960 err1: | |
961 result = 1; | |
962 return result; | |
963 #endif | |
964 #if _WIN32 | |
965 DWORD size; | |
966 DWORD numread; | |
967 HANDLE h; | |
968 int result = 0; | |
969 char *name; | |
970 | |
971 name = this->name->toChars(); | |
972 h = CreateFileA(name,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING, | |
973 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,0); | |
974 if (h == INVALID_HANDLE_VALUE) | |
975 goto err1; | |
976 | |
977 if (!ref) | |
978 mem.free(buffer); | |
979 ref = 0; | |
980 | |
981 size = GetFileSize(h,NULL); | |
982 buffer = (unsigned char *) mem.malloc(size + 2); | |
983 if (!buffer) | |
984 goto err2; | |
985 | |
986 if (ReadFile(h,buffer,size,&numread,NULL) != TRUE) | |
987 goto err2; | |
988 | |
989 if (numread != size) | |
990 goto err2; | |
991 | |
992 if (touchtime) | |
993 { | |
994 if (!GetFileTime(h, NULL, NULL, &((WIN32_FIND_DATAA *)touchtime)->ftLastWriteTime)) | |
995 goto err2; | |
996 } | |
997 | |
998 if (!CloseHandle(h)) | |
999 goto err; | |
1000 | |
1001 len = size; | |
1002 | |
1003 // Always store a wchar ^Z past end of buffer so scanner has a sentinel | |
1004 buffer[size] = 0; // ^Z is obsolete, use 0 | |
1005 buffer[size + 1] = 0; | |
1006 return 0; | |
1007 | |
1008 err2: | |
1009 CloseHandle(h); | |
1010 err: | |
1011 mem.free(buffer); | |
1012 buffer = NULL; | |
1013 len = 0; | |
1014 | |
1015 err1: | |
1016 result = 1; | |
1017 return result; | |
1018 #endif | |
1019 } | |
1020 | |
1021 /***************************** | |
1022 * Read a file with memory mapped file I/O. | |
1023 */ | |
1024 | |
1025 int File::mmread() | |
1026 { | |
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
|
1027 #if POSIX |
336 | 1028 return read(); |
1029 #endif | |
1030 #if _WIN32 | |
1031 HANDLE hFile; | |
1032 HANDLE hFileMap; | |
1033 DWORD size; | |
1034 char *name; | |
1035 | |
1036 name = this->name->toChars(); | |
1037 hFile = CreateFile(name, GENERIC_READ, | |
1038 FILE_SHARE_READ, NULL, | |
1039 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); | |
1040 if (hFile == INVALID_HANDLE_VALUE) | |
1041 goto Lerr; | |
1042 size = GetFileSize(hFile, NULL); | |
1043 //printf(" file created, size %d\n", size); | |
1044 | |
1045 hFileMap = CreateFileMapping(hFile,NULL,PAGE_READONLY,0,size,NULL); | |
1046 if (CloseHandle(hFile) != TRUE) | |
1047 goto Lerr; | |
1048 | |
1049 if (hFileMap == NULL) | |
1050 goto Lerr; | |
1051 | |
1052 //printf(" mapping created\n"); | |
1053 | |
1054 if (!ref) | |
1055 mem.free(buffer); | |
1056 ref = 2; | |
1057 buffer = (unsigned char *)MapViewOfFileEx(hFileMap, FILE_MAP_READ,0,0,size,NULL); | |
1058 if (CloseHandle(hFileMap) != TRUE) | |
1059 goto Lerr; | |
1060 if (buffer == NULL) // mapping view failed | |
1061 goto Lerr; | |
1062 | |
1063 len = size; | |
1064 //printf(" buffer = %p\n", buffer); | |
1065 | |
1066 return 0; | |
1067 | |
1068 Lerr: | |
1069 return GetLastError(); // failure | |
1070 #endif | |
1071 } | |
1072 | |
1073 /********************************************* | |
1074 * Write a file. | |
1075 * Returns: | |
1076 * 0 success | |
1077 */ | |
1078 | |
1079 int File::write() | |
1080 { | |
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
|
1081 #if POSIX |
336 | 1082 int fd; |
1083 ssize_t numwritten; | |
1084 char *name; | |
1085 | |
1086 name = this->name->toChars(); | |
1087 fd = open(name, O_CREAT | O_WRONLY | O_TRUNC, 0644); | |
1088 if (fd == -1) | |
1089 goto err; | |
1090 | |
1091 numwritten = ::write(fd, buffer, len); | |
1092 if (len != numwritten) | |
1093 goto err2; | |
1094 | |
1095 if (close(fd) == -1) | |
1096 goto err; | |
1097 | |
1098 if (touchtime) | |
1099 { struct utimbuf ubuf; | |
1100 | |
1101 ubuf.actime = ((struct stat *)touchtime)->st_atime; | |
1102 ubuf.modtime = ((struct stat *)touchtime)->st_mtime; | |
1103 if (utime(name, &ubuf)) | |
1104 goto err; | |
1105 } | |
1106 return 0; | |
1107 | |
1108 err2: | |
1109 close(fd); | |
1110 ::remove(name); | |
1111 err: | |
1112 return 1; | |
1113 #endif | |
1114 #if _WIN32 | |
1115 HANDLE h; | |
1116 DWORD numwritten; | |
1117 char *name; | |
1118 | |
1119 name = this->name->toChars(); | |
1120 h = CreateFileA(name,GENERIC_WRITE,0,NULL,CREATE_ALWAYS, | |
1121 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,NULL); | |
1122 if (h == INVALID_HANDLE_VALUE) | |
1123 goto err; | |
1124 | |
1125 if (WriteFile(h,buffer,len,&numwritten,NULL) != TRUE) | |
1126 goto err2; | |
1127 | |
1128 if (len != numwritten) | |
1129 goto err2; | |
1130 | |
1131 if (touchtime) { | |
1132 SetFileTime(h, NULL, NULL, &((WIN32_FIND_DATAA *)touchtime)->ftLastWriteTime); | |
1133 } | |
1134 if (!CloseHandle(h)) | |
1135 goto err; | |
1136 return 0; | |
1137 | |
1138 err2: | |
1139 CloseHandle(h); | |
1140 DeleteFileA(name); | |
1141 err: | |
1142 return 1; | |
1143 #endif | |
1144 } | |
1145 | |
1146 /********************************************* | |
1147 * Append to a file. | |
1148 * Returns: | |
1149 * 0 success | |
1150 */ | |
1151 | |
1152 int File::append() | |
1153 { | |
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
|
1154 #if POSIX |
336 | 1155 return 1; |
1156 #endif | |
1157 #if _WIN32 | |
1158 HANDLE h; | |
1159 DWORD numwritten; | |
1160 char *name; | |
1161 | |
1162 name = this->name->toChars(); | |
1163 h = CreateFileA(name,GENERIC_WRITE,0,NULL,OPEN_ALWAYS, | |
1164 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,NULL); | |
1165 if (h == INVALID_HANDLE_VALUE) | |
1166 goto err; | |
1167 | |
1168 #if 1 | |
1169 SetFilePointer(h, 0, NULL, FILE_END); | |
1170 #else // INVALID_SET_FILE_POINTER doesn't seem to have a definition | |
1171 if (SetFilePointer(h, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER) | |
1172 goto err; | |
1173 #endif | |
1174 | |
1175 if (WriteFile(h,buffer,len,&numwritten,NULL) != TRUE) | |
1176 goto err2; | |
1177 | |
1178 if (len != numwritten) | |
1179 goto err2; | |
1180 | |
1181 if (touchtime) { | |
1182 SetFileTime(h, NULL, NULL, &((WIN32_FIND_DATAA *)touchtime)->ftLastWriteTime); | |
1183 } | |
1184 if (!CloseHandle(h)) | |
1185 goto err; | |
1186 return 0; | |
1187 | |
1188 err2: | |
1189 CloseHandle(h); | |
1190 err: | |
1191 return 1; | |
1192 #endif | |
1193 } | |
1194 | |
1195 /************************************** | |
1196 */ | |
1197 | |
1198 void File::readv() | |
1199 { | |
1200 if (read()) | |
1201 error("Error reading file '%s'\n",name->toChars()); | |
1202 } | |
1203 | |
1204 /************************************** | |
1205 */ | |
1206 | |
1207 void File::mmreadv() | |
1208 { | |
1209 if (mmread()) | |
1210 readv(); | |
1211 } | |
1212 | |
1213 void File::writev() | |
1214 { | |
1215 if (write()) | |
1216 error("Error writing file '%s'\n",name->toChars()); | |
1217 } | |
1218 | |
1219 void File::appendv() | |
1220 { | |
1221 if (write()) | |
1222 error("Error appending to file '%s'\n",name->toChars()); | |
1223 } | |
1224 | |
1225 /******************************************* | |
1226 * Return !=0 if file exists. | |
1227 * 0: file doesn't exist | |
1228 * 1: normal file | |
1229 * 2: directory | |
1230 */ | |
1231 | |
1232 int File::exists() | |
1233 { | |
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
|
1234 #if POSIX |
336 | 1235 return 0; |
1236 #endif | |
1237 #if _WIN32 | |
1238 DWORD dw; | |
1239 int result; | |
1240 char *name; | |
1241 | |
1242 name = this->name->toChars(); | |
1243 if (touchtime) | |
1244 dw = ((WIN32_FIND_DATAA *)touchtime)->dwFileAttributes; | |
1245 else | |
1246 dw = GetFileAttributesA(name); | |
1247 if (dw == -1L) | |
1248 result = 0; | |
1249 else if (dw & FILE_ATTRIBUTE_DIRECTORY) | |
1250 result = 2; | |
1251 else | |
1252 result = 1; | |
1253 return result; | |
1254 #endif | |
1255 } | |
1256 | |
1257 void File::remove() | |
1258 { | |
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
|
1259 #if POSIX |
336 | 1260 ::remove(this->name->toChars()); |
1261 #endif | |
1262 #if _WIN32 | |
1263 DeleteFileA(this->name->toChars()); | |
1264 #endif | |
1265 } | |
1266 | |
1267 Array *File::match(char *n) | |
1268 { | |
1269 return match(new FileName(n, 0)); | |
1270 } | |
1271 | |
1272 Array *File::match(FileName *n) | |
1273 { | |
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
|
1274 #if POSIX |
336 | 1275 return NULL; |
1276 #endif | |
1277 #if _WIN32 | |
1278 HANDLE h; | |
1279 WIN32_FIND_DATAA fileinfo; | |
1280 Array *a; | |
1281 char *c; | |
1282 char *name; | |
1283 | |
1284 a = new Array(); | |
1285 c = n->toChars(); | |
1286 name = n->name(); | |
1287 h = FindFirstFileA(c,&fileinfo); | |
1288 if (h != INVALID_HANDLE_VALUE) | |
1289 { | |
1290 do | |
1291 { | |
1292 // Glue path together with name | |
1293 char *fn; | |
1294 File *f; | |
1295 | |
1296 fn = (char *)mem.malloc(name - c + strlen(fileinfo.cFileName) + 1); | |
1297 memcpy(fn, c, name - c); | |
1298 strcpy(fn + (name - c), fileinfo.cFileName); | |
1299 f = new File(fn); | |
1300 f->touchtime = mem.malloc(sizeof(WIN32_FIND_DATAA)); | |
1301 memcpy(f->touchtime, &fileinfo, sizeof(fileinfo)); | |
1302 a->push(f); | |
1303 } while (FindNextFileA(h,&fileinfo) != FALSE); | |
1304 FindClose(h); | |
1305 } | |
1306 return a; | |
1307 #endif | |
1308 } | |
1309 | |
1310 int File::compareTime(File *f) | |
1311 { | |
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
|
1312 #if POSIX |
336 | 1313 return 0; |
1314 #endif | |
1315 #if _WIN32 | |
1316 if (!touchtime) | |
1317 stat(); | |
1318 if (!f->touchtime) | |
1319 f->stat(); | |
1320 return CompareFileTime(&((WIN32_FIND_DATAA *)touchtime)->ftLastWriteTime, &((WIN32_FIND_DATAA *)f->touchtime)->ftLastWriteTime); | |
1321 #endif | |
1322 } | |
1323 | |
1324 void File::stat() | |
1325 { | |
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
|
1326 #if POSIX |
336 | 1327 if (!touchtime) |
1328 { | |
1329 touchtime = mem.calloc(1, sizeof(struct stat)); | |
1330 } | |
1331 #endif | |
1332 #if _WIN32 | |
1333 HANDLE h; | |
1334 | |
1335 if (!touchtime) | |
1336 { | |
1337 touchtime = mem.calloc(1, sizeof(WIN32_FIND_DATAA)); | |
1338 } | |
1339 h = FindFirstFileA(name->toChars(),(WIN32_FIND_DATAA *)touchtime); | |
1340 if (h != INVALID_HANDLE_VALUE) | |
1341 { | |
1342 FindClose(h); | |
1343 } | |
1344 #endif | |
1345 } | |
1346 | |
1347 void File::checkoffset(size_t offset, size_t nbytes) | |
1348 { | |
1349 if (offset > len || offset + nbytes > len) | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
872
diff
changeset
|
1350 error("Corrupt file '%s': offset x%zx off end of file",toChars(),offset); |
336 | 1351 } |
1352 | |
1353 char *File::toChars() | |
1354 { | |
1355 return name->toChars(); | |
1356 } | |
1357 | |
1358 | |
1359 /************************* OutBuffer *************************/ | |
1360 | |
1361 OutBuffer::OutBuffer() | |
1362 { | |
1363 data = NULL; | |
1364 offset = 0; | |
1365 size = 0; | |
1366 } | |
1367 | |
1368 OutBuffer::~OutBuffer() | |
1369 { | |
1370 mem.free(data); | |
1371 } | |
1372 | |
1373 void *OutBuffer::extractData() | |
1374 { | |
1375 void *p; | |
1376 | |
1377 p = (void *)data; | |
1378 data = NULL; | |
1379 offset = 0; | |
1380 size = 0; | |
1381 return p; | |
1382 } | |
1383 | |
1384 void OutBuffer::mark() | |
1385 { | |
1386 mem.mark(data); | |
1387 } | |
1388 | |
1389 void OutBuffer::reserve(unsigned nbytes) | |
1390 { | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
872
diff
changeset
|
1391 //printf("OutBuffer::reserve: size = %d, offset = %d, nbytes = %d\n", size, offset, nbytes); |
336 | 1392 if (size - offset < nbytes) |
1393 { | |
1110
fd631764eaac
Revert removal of "+2" from Outbuffer::reserve function for x64. Unless
Kelly Wilson <wilsonk cpsc.ucalgary.ca>
parents:
1103
diff
changeset
|
1394 #if defined (__x86_64__) |
fd631764eaac
Revert removal of "+2" from Outbuffer::reserve function for x64. Unless
Kelly Wilson <wilsonk cpsc.ucalgary.ca>
parents:
1103
diff
changeset
|
1395 size = (offset + nbytes) * 2 + 2; |
fd631764eaac
Revert removal of "+2" from Outbuffer::reserve function for x64. Unless
Kelly Wilson <wilsonk cpsc.ucalgary.ca>
parents:
1103
diff
changeset
|
1396 #else |
1111
0f8aeb31678c
Fix 32bit "+2" typo for Outbuffer::reserve
Kelly Wilson <wilsonk cpsc.ucalgary.ca>
parents:
1110
diff
changeset
|
1397 size = (offset + nbytes) * 2; |
1110
fd631764eaac
Revert removal of "+2" from Outbuffer::reserve function for x64. Unless
Kelly Wilson <wilsonk cpsc.ucalgary.ca>
parents:
1103
diff
changeset
|
1398 #endif |
336 | 1399 data = (unsigned char *)mem.realloc(data, size); |
1400 } | |
1401 } | |
1402 | |
1403 void OutBuffer::reset() | |
1404 { | |
1405 offset = 0; | |
1406 } | |
1407 | |
1408 void OutBuffer::setsize(unsigned size) | |
1409 { | |
1410 offset = size; | |
1411 } | |
1412 | |
1413 void OutBuffer::write(const void *data, unsigned nbytes) | |
1414 { | |
1415 reserve(nbytes); | |
1416 memcpy(this->data + offset, data, nbytes); | |
1417 offset += nbytes; | |
1418 } | |
1419 | |
1420 void OutBuffer::writebstring(unsigned char *string) | |
1421 { | |
1422 write(string,*string + 1); | |
1423 } | |
1424 | |
1425 void OutBuffer::writestring(const char *string) | |
1426 { | |
1427 write(string,strlen(string)); | |
1428 } | |
1429 | |
1430 void OutBuffer::writedstring(const char *string) | |
1431 { | |
1432 #if M_UNICODE | |
1433 for (; *string; string++) | |
1434 { | |
1435 writedchar(*string); | |
1436 } | |
1437 #else | |
1438 write(string,strlen(string)); | |
1439 #endif | |
1440 } | |
1441 | |
1442 void OutBuffer::writedstring(const wchar_t *string) | |
1443 { | |
1444 #if M_UNICODE | |
1445 write(string,wcslen(string) * sizeof(wchar_t)); | |
1446 #else | |
1447 for (; *string; string++) | |
1448 { | |
1449 writedchar(*string); | |
1450 } | |
1451 #endif | |
1452 } | |
1453 | |
658
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
571
diff
changeset
|
1454 void OutBuffer::prependstring(const char *string) |
336 | 1455 { unsigned len; |
1456 | |
1457 len = strlen(string); | |
1458 reserve(len); | |
1459 memmove(data + len, data, offset); | |
1460 memcpy(data, string, len); | |
1461 offset += len; | |
1462 } | |
1463 | |
1464 void OutBuffer::writenl() | |
1465 { | |
1466 #if _WIN32 | |
1467 #if M_UNICODE | |
1468 write4(0x000A000D); // newline is CR,LF on Microsoft OS's | |
1469 #else | |
1470 writeword(0x0A0D); // newline is CR,LF on Microsoft OS's | |
1471 #endif | |
1472 #else | |
1473 #if M_UNICODE | |
1474 writeword('\n'); | |
1475 #else | |
1476 writeByte('\n'); | |
1477 #endif | |
1478 #endif | |
1479 } | |
1480 | |
1481 void OutBuffer::writeByte(unsigned b) | |
1482 { | |
1483 reserve(1); | |
1484 this->data[offset] = (unsigned char)b; | |
1485 offset++; | |
1486 } | |
1487 | |
1488 void OutBuffer::writeUTF8(unsigned b) | |
1489 { | |
1490 reserve(6); | |
1491 if (b <= 0x7F) | |
1492 { | |
1493 this->data[offset] = (unsigned char)b; | |
1494 offset++; | |
1495 } | |
1496 else if (b <= 0x7FF) | |
1497 { | |
1498 this->data[offset + 0] = (unsigned char)((b >> 6) | 0xC0); | |
1499 this->data[offset + 1] = (unsigned char)((b & 0x3F) | 0x80); | |
1500 offset += 2; | |
1501 } | |
1502 else if (b <= 0xFFFF) | |
1503 { | |
1504 this->data[offset + 0] = (unsigned char)((b >> 12) | 0xE0); | |
1505 this->data[offset + 1] = (unsigned char)(((b >> 6) & 0x3F) | 0x80); | |
1506 this->data[offset + 2] = (unsigned char)((b & 0x3F) | 0x80); | |
1507 offset += 3; | |
1508 } | |
1509 else if (b <= 0x1FFFFF) | |
1510 { | |
1511 this->data[offset + 0] = (unsigned char)((b >> 18) | 0xF0); | |
1512 this->data[offset + 1] = (unsigned char)(((b >> 12) & 0x3F) | 0x80); | |
1513 this->data[offset + 2] = (unsigned char)(((b >> 6) & 0x3F) | 0x80); | |
1514 this->data[offset + 3] = (unsigned char)((b & 0x3F) | 0x80); | |
1515 offset += 4; | |
1516 } | |
1517 else if (b <= 0x3FFFFFF) | |
1518 { | |
1519 this->data[offset + 0] = (unsigned char)((b >> 24) | 0xF8); | |
1520 this->data[offset + 1] = (unsigned char)(((b >> 18) & 0x3F) | 0x80); | |
1521 this->data[offset + 2] = (unsigned char)(((b >> 12) & 0x3F) | 0x80); | |
1522 this->data[offset + 3] = (unsigned char)(((b >> 6) & 0x3F) | 0x80); | |
1523 this->data[offset + 4] = (unsigned char)((b & 0x3F) | 0x80); | |
1524 offset += 5; | |
1525 } | |
1526 else if (b <= 0x7FFFFFFF) | |
1527 { | |
1528 this->data[offset + 0] = (unsigned char)((b >> 30) | 0xFC); | |
1529 this->data[offset + 1] = (unsigned char)(((b >> 24) & 0x3F) | 0x80); | |
1530 this->data[offset + 2] = (unsigned char)(((b >> 18) & 0x3F) | 0x80); | |
1531 this->data[offset + 3] = (unsigned char)(((b >> 12) & 0x3F) | 0x80); | |
1532 this->data[offset + 4] = (unsigned char)(((b >> 6) & 0x3F) | 0x80); | |
1533 this->data[offset + 5] = (unsigned char)((b & 0x3F) | 0x80); | |
1534 offset += 6; | |
1535 } | |
1536 else | |
1537 assert(0); | |
1538 } | |
1539 | |
1540 void OutBuffer::writedchar(unsigned b) | |
1541 { | |
1542 reserve(Dchar_mbmax * sizeof(dchar)); | |
1543 offset = (unsigned char *)Dchar::put((dchar *)(this->data + offset), (dchar)b) - | |
1544 this->data; | |
1545 } | |
1546 | |
1547 void OutBuffer::prependbyte(unsigned b) | |
1548 { | |
1549 reserve(1); | |
1550 memmove(data + 1, data, offset); | |
1551 data[0] = (unsigned char)b; | |
1552 offset++; | |
1553 } | |
1554 | |
1555 void OutBuffer::writeword(unsigned w) | |
1556 { | |
1557 reserve(2); | |
1558 *(unsigned short *)(this->data + offset) = (unsigned short)w; | |
1559 offset += 2; | |
1560 } | |
1561 | |
1562 void OutBuffer::writeUTF16(unsigned w) | |
1563 { | |
1564 reserve(4); | |
1565 if (w <= 0xFFFF) | |
1566 { | |
1567 *(unsigned short *)(this->data + offset) = (unsigned short)w; | |
1568 offset += 2; | |
1569 } | |
1570 else if (w <= 0x10FFFF) | |
1571 { | |
1572 *(unsigned short *)(this->data + offset) = (unsigned short)((w >> 10) + 0xD7C0); | |
1573 *(unsigned short *)(this->data + offset + 2) = (unsigned short)((w & 0x3FF) | 0xDC00); | |
1574 offset += 4; | |
1575 } | |
1576 else | |
1577 assert(0); | |
1578 } | |
1579 | |
1580 void OutBuffer::write4(unsigned w) | |
1581 { | |
1582 reserve(4); | |
1583 *(unsigned long *)(this->data + offset) = w; | |
1584 offset += 4; | |
1585 } | |
1586 | |
1587 void OutBuffer::write(OutBuffer *buf) | |
1588 { | |
1589 if (buf) | |
1590 { reserve(buf->offset); | |
1591 memcpy(data + offset, buf->data, buf->offset); | |
1592 offset += buf->offset; | |
1593 } | |
1594 } | |
1595 | |
1596 void OutBuffer::write(Object *obj) | |
1597 { | |
1598 if (obj) | |
1599 { | |
1600 writestring(obj->toChars()); | |
1601 } | |
1602 } | |
1603 | |
1604 void OutBuffer::fill0(unsigned nbytes) | |
1605 { | |
1606 reserve(nbytes); | |
1607 memset(data + offset,0,nbytes); | |
1608 offset += nbytes; | |
1609 } | |
1610 | |
1611 void OutBuffer::align(unsigned size) | |
1612 { unsigned nbytes; | |
1613 | |
1614 nbytes = ((offset + size - 1) & ~(size - 1)) - offset; | |
1615 fill0(nbytes); | |
1616 } | |
1617 | |
846
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
761
diff
changeset
|
1618 |
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 // 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
|
1621 // 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
|
1622 // such as %z and %j |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
761
diff
changeset
|
1623 #if _MSC_VER |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
761
diff
changeset
|
1624 using std::string; |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
761
diff
changeset
|
1625 using std::wstring; |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
761
diff
changeset
|
1626 |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
761
diff
changeset
|
1627 template<typename S> |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
761
diff
changeset
|
1628 inline void |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
761
diff
changeset
|
1629 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
|
1630 { |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
761
diff
changeset
|
1631 assert(!what.empty()); |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
761
diff
changeset
|
1632 size_t pos = str.find(what); |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
761
diff
changeset
|
1633 while (pos != S::npos) |
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 str.replace(pos, what.size(), replacement); |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
761
diff
changeset
|
1636 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
|
1637 } |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
761
diff
changeset
|
1638 } |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
761
diff
changeset
|
1639 #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
|
1640 S tmp = f; \ |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
761
diff
changeset
|
1641 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
|
1642 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
|
1643 f = tmp.c_str(); |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
761
diff
changeset
|
1644 #else |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
761
diff
changeset
|
1645 #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
|
1646 #endif |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
761
diff
changeset
|
1647 |
336 | 1648 void OutBuffer::vprintf(const char *format, va_list args) |
1649 { | |
1650 char buffer[128]; | |
1651 char *p; | |
1652 unsigned psize; | |
1653 int count; | |
1654 | |
846
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
761
diff
changeset
|
1655 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
|
1656 |
336 | 1657 p = buffer; |
1658 psize = sizeof(buffer); | |
1659 for (;;) | |
1660 { | |
1661 #if _WIN32 | |
1662 count = _vsnprintf(p,psize,format,args); | |
1663 if (count != -1) | |
1664 break; | |
1665 psize *= 2; | |
761
fa306ca8843b
Applied fvbommel's patch from #112
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
741
diff
changeset
|
1666 #elif POSIX |
846
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
761
diff
changeset
|
1667 va_list va; |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
761
diff
changeset
|
1668 va_copy(va, args); |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
761
diff
changeset
|
1669 /* |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
761
diff
changeset
|
1670 The functions vprintf(), vfprintf(), vsprintf(), vsnprintf() |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
761
diff
changeset
|
1671 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
|
1672 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
|
1673 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
|
1674 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
|
1675 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
|
1676 va_end(ap) itself afterwards. |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
761
diff
changeset
|
1677 */ |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
761
diff
changeset
|
1678 count = vsnprintf(p,psize,format,va); |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
761
diff
changeset
|
1679 va_end(va); |
336 | 1680 if (count == -1) |
1681 psize *= 2; | |
1682 else if (count >= psize) | |
1683 psize = count + 1; | |
1684 else | |
1685 break; | |
1686 #endif | |
1687 p = (char *) alloca(psize); // buffer too small, try again with larger size | |
1688 } | |
1689 write(p,count); | |
1690 } | |
1691 | |
1692 #if M_UNICODE | |
1693 void OutBuffer::vprintf(const wchar_t *format, va_list args) | |
1694 { | |
1695 dchar buffer[128]; | |
1696 dchar *p; | |
1697 unsigned psize; | |
1698 int count; | |
1699 | |
846
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
761
diff
changeset
|
1700 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
|
1701 |
336 | 1702 p = buffer; |
1703 psize = sizeof(buffer) / sizeof(buffer[0]); | |
1704 for (;;) | |
1705 { | |
1706 #if _WIN32 | |
1707 count = _vsnwprintf(p,psize,format,args); | |
1708 if (count != -1) | |
1709 break; | |
1710 psize *= 2; | |
1711 #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
|
1712 #if POSIX |
846
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
761
diff
changeset
|
1713 va_list va; |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
761
diff
changeset
|
1714 va_copy(va, args); |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
761
diff
changeset
|
1715 count = vsnwprintf(p,psize,format,va); |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
761
diff
changeset
|
1716 va_end(va); |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
761
diff
changeset
|
1717 |
336 | 1718 if (count == -1) |
1719 psize *= 2; | |
1720 else if (count >= psize) | |
1721 psize = count + 1; | |
1722 else | |
1723 break; | |
1724 #endif | |
1725 p = (dchar *) alloca(psize * 2); // buffer too small, try again with larger size | |
1726 } | |
1727 write(p,count * 2); | |
1728 } | |
1729 #endif | |
1730 | |
1731 void OutBuffer::printf(const char *format, ...) | |
1732 { | |
1733 va_list ap; | |
1734 va_start(ap, format); | |
1735 vprintf(format,ap); | |
1736 va_end(ap); | |
1737 } | |
1738 | |
1739 #if M_UNICODE | |
1740 void OutBuffer::printf(const wchar_t *format, ...) | |
1741 { | |
1742 va_list ap; | |
1743 va_start(ap, format); | |
1744 vprintf(format,ap); | |
1745 va_end(ap); | |
1746 } | |
1747 #endif | |
1748 | |
1749 void OutBuffer::bracket(char left, char right) | |
1750 { | |
1751 reserve(2); | |
1752 memmove(data + 1, data, offset); | |
1753 data[0] = left; | |
1754 data[offset + 1] = right; | |
1755 offset += 2; | |
1756 } | |
1757 | |
1758 /****************** | |
1759 * Insert left at i, and right at j. | |
1760 * Return index just past right. | |
1761 */ | |
1762 | |
658
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
571
diff
changeset
|
1763 unsigned OutBuffer::bracket(unsigned i, const char *left, unsigned j, const char *right) |
336 | 1764 { |
1765 size_t leftlen = strlen(left); | |
1766 size_t rightlen = strlen(right); | |
1767 reserve(leftlen + rightlen); | |
1768 insert(i, left, leftlen); | |
1769 insert(j + leftlen, right, rightlen); | |
1770 return j + leftlen + rightlen; | |
1771 } | |
1772 | |
1773 void OutBuffer::spread(unsigned offset, unsigned nbytes) | |
1774 { | |
1775 reserve(nbytes); | |
1776 memmove(data + offset + nbytes, data + offset, | |
1777 this->offset - offset); | |
1778 this->offset += nbytes; | |
1779 } | |
1780 | |
1781 /**************************************** | |
1782 * Returns: offset + nbytes | |
1783 */ | |
1784 | |
1785 unsigned OutBuffer::insert(unsigned offset, const void *p, unsigned nbytes) | |
1786 { | |
1787 spread(offset, nbytes); | |
1788 memmove(data + offset, p, nbytes); | |
1789 return offset + nbytes; | |
1790 } | |
1791 | |
1792 void OutBuffer::remove(unsigned offset, unsigned nbytes) | |
1793 { | |
1794 memmove(data + offset, data + offset + nbytes, this->offset - (offset + nbytes)); | |
1795 this->offset -= nbytes; | |
1796 } | |
1797 | |
1798 char *OutBuffer::toChars() | |
1799 { | |
1800 writeByte(0); | |
1801 return (char *)data; | |
1802 } | |
1803 | |
1804 /********************************* Bits ****************************/ | |
1805 | |
1806 Bits::Bits() | |
1807 { | |
1808 data = NULL; | |
1809 bitdim = 0; | |
1810 allocdim = 0; | |
1811 } | |
1812 | |
1813 Bits::~Bits() | |
1814 { | |
1815 mem.free(data); | |
1816 } | |
1817 | |
1818 void Bits::mark() | |
1819 { | |
1820 mem.mark(data); | |
1821 } | |
1822 | |
1823 void Bits::resize(unsigned bitdim) | |
1824 { | |
1825 unsigned allocdim; | |
1826 unsigned mask; | |
1827 | |
1828 allocdim = (bitdim + 31) / 32; | |
1829 data = (unsigned *)mem.realloc(data, allocdim * sizeof(data[0])); | |
1830 if (this->allocdim < allocdim) | |
1831 memset(data + this->allocdim, 0, (allocdim - this->allocdim) * sizeof(data[0])); | |
1832 | |
1833 // Clear other bits in last word | |
1834 mask = (1 << (bitdim & 31)) - 1; | |
1835 if (mask) | |
1836 data[allocdim - 1] &= ~mask; | |
1837 | |
1838 this->bitdim = bitdim; | |
1839 this->allocdim = allocdim; | |
1840 } | |
1841 | |
1842 void Bits::set(unsigned bitnum) | |
1843 { | |
1844 data[bitnum / 32] |= 1 << (bitnum & 31); | |
1845 } | |
1846 | |
1847 void Bits::clear(unsigned bitnum) | |
1848 { | |
1849 data[bitnum / 32] &= ~(1 << (bitnum & 31)); | |
1850 } | |
1851 | |
1852 int Bits::test(unsigned bitnum) | |
1853 { | |
1854 return data[bitnum / 32] & (1 << (bitnum & 31)); | |
1855 } | |
1856 | |
1857 void Bits::set() | |
1858 { unsigned mask; | |
1859 | |
1860 memset(data, ~0, allocdim * sizeof(data[0])); | |
1861 | |
1862 // Clear other bits in last word | |
1863 mask = (1 << (bitdim & 31)) - 1; | |
1864 if (mask) | |
1865 data[allocdim - 1] &= mask; | |
1866 } | |
1867 | |
1868 void Bits::clear() | |
1869 { | |
1870 memset(data, 0, allocdim * sizeof(data[0])); | |
1871 } | |
1872 | |
1873 void Bits::copy(Bits *from) | |
1874 { | |
1875 assert(bitdim == from->bitdim); | |
1876 memcpy(data, from->data, allocdim * sizeof(data[0])); | |
1877 } | |
1878 | |
1879 Bits *Bits::clone() | |
1880 { | |
1881 Bits *b; | |
1882 | |
1883 b = new Bits(); | |
1884 b->resize(bitdim); | |
1885 b->copy(this); | |
1886 return b; | |
1887 } | |
1888 | |
1889 void Bits::sub(Bits *b) | |
1890 { | |
1891 unsigned u; | |
1892 | |
1893 for (u = 0; u < allocdim; u++) | |
1894 data[u] &= ~b->data[u]; | |
1895 } | |
1896 | |
1897 | |
1898 | |
1899 | |
1900 | |
1901 | |
1902 | |
1903 | |
1904 | |
1905 | |
1906 | |
1907 | |
1908 | |
1909 | |
1910 |