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