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