comparison dmd2/root.c @ 758:f04dde6e882c

Added initial D2 support, D2 frontend and changes to codegen to make things compile.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Tue, 11 Nov 2008 01:38:48 +0100
parents
children fa306ca8843b
comparison
equal deleted inserted replaced
757:2c730d530c98 758:f04dde6e882c
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
26 #if POSIX
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 {
191 return (char *)"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(const char *path, const char *name)
316 { char *f;
317 size_t pathlen;
318 size_t namelen;
319
320 if (!path || !*path)
321 return (char *)name;
322 pathlen = strlen(path);
323 namelen = strlen(name);
324 f = (char *)mem.malloc(pathlen + 1 + namelen + 1);
325 memcpy(f, path, pathlen);
326
327 if (
328 path[pathlen - 1] != '/'
329 #if _WIN32
330 && path[pathlen - 1] != '\\' && path[pathlen - 1] != ':'
331 #endif
332 )
333 { f[pathlen] = '/';
334 pathlen++;
335 }
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
376 #if POSIX
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
390 #if POSIX
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 {
485 return
486 #if _WIN32
487 (*name == '\\') ||
488 (*name == '/') ||
489 (*name && name[1] == ':') ||
490 #endif
491 (*name == '/');
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;
511
512 case '/':
513 break;
514
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 {
566
567 case '/':
568 return e + 1;
569
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 {
603
604 if (n[-1] == '/')
605 n--;
606
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);
639
640 if (
641 path[pathlen - 1] != '/'
642 #if _WIN32
643 && path[pathlen - 1] != '\\' && path[pathlen - 1] != ':'
644 #endif
645 )
646 { f[pathlen] = '/';
647 pathlen++;
648 }
649
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;
714 #if POSIX
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
733 #if POSIX
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
747 char *FileName::searchPath(Array *path, const char *name, int cwd)
748 {
749 if (absolute(name))
750 {
751 return exists(name) ? (char *)name : NULL;
752 }
753 if (cwd)
754 {
755 if (exists(name))
756 return (char *)name;
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 {
775 #if POSIX
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
822 #if POSIX
823 if (path[strlen(path) - 1] != '\\')
824 #endif
825 {
826 //printf("mkdir(%s)\n", path);
827 #if _WIN32
828 if (mkdir(path))
829 #endif
830 #if POSIX
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 {
886 #if POSIX
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 {
1018 #if POSIX
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 {
1072 #if POSIX
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 {
1145 #if POSIX
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 {
1225 #if POSIX
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 {
1250 #if POSIX
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 {
1265 #if POSIX
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 {
1303 #if POSIX
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 {
1317 #if POSIX
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 {
1382 //printf("OutBuffer::reserve: size = %d, offset = %d, nbytes = %d\n", size, offset, nbytes);
1383 if (size - offset < nbytes)
1384 {
1385 #if defined (__x86_64__)
1386 size = (offset + nbytes) * 2+2;
1387 #else
1388 size = (offset + nbytes) * 2;
1389 #endif
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
1445 void OutBuffer::prependstring(const char *string)
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
1616 p = buffer;
1617 psize = sizeof(buffer);
1618 for (;;)
1619 {
1620 #if _WIN32
1621 count = _vsnprintf(p,psize,format,args);
1622 if (count != -1)
1623 break;
1624 psize *= 2;
1625 #endif
1626 #if POSIX
1627 count = vsnprintf(p,psize,format,args);
1628 if (count == -1)
1629 psize *= 2;
1630 else if (count >= psize)
1631 psize = count + 1;
1632 else
1633 break;
1634 #endif
1635 p = (char *) alloca(psize); // buffer too small, try again with larger size
1636 }
1637 write(p,count);
1638 }
1639
1640 #if M_UNICODE
1641 void OutBuffer::vprintf(const wchar_t *format, va_list args)
1642 {
1643 dchar buffer[128];
1644 dchar *p;
1645 unsigned psize;
1646 int count;
1647
1648 p = buffer;
1649 psize = sizeof(buffer) / sizeof(buffer[0]);
1650 for (;;)
1651 {
1652 #if _WIN32
1653 count = _vsnwprintf(p,psize,format,args);
1654 if (count != -1)
1655 break;
1656 psize *= 2;
1657 #endif
1658 #if POSIX
1659 count = vsnwprintf(p,psize,format,args);
1660 if (count == -1)
1661 psize *= 2;
1662 else if (count >= psize)
1663 psize = count + 1;
1664 else
1665 break;
1666 #endif
1667 p = (dchar *) alloca(psize * 2); // buffer too small, try again with larger size
1668 }
1669 write(p,count * 2);
1670 }
1671 #endif
1672
1673 void OutBuffer::printf(const char *format, ...)
1674 {
1675 va_list ap;
1676 va_start(ap, format);
1677 vprintf(format,ap);
1678 va_end(ap);
1679 }
1680
1681 #if M_UNICODE
1682 void OutBuffer::printf(const wchar_t *format, ...)
1683 {
1684 va_list ap;
1685 va_start(ap, format);
1686 vprintf(format,ap);
1687 va_end(ap);
1688 }
1689 #endif
1690
1691 void OutBuffer::bracket(char left, char right)
1692 {
1693 reserve(2);
1694 memmove(data + 1, data, offset);
1695 data[0] = left;
1696 data[offset + 1] = right;
1697 offset += 2;
1698 }
1699
1700 /******************
1701 * Insert left at i, and right at j.
1702 * Return index just past right.
1703 */
1704
1705 unsigned OutBuffer::bracket(unsigned i, const char *left, unsigned j, const char *right)
1706 {
1707 size_t leftlen = strlen(left);
1708 size_t rightlen = strlen(right);
1709 reserve(leftlen + rightlen);
1710 insert(i, left, leftlen);
1711 insert(j + leftlen, right, rightlen);
1712 return j + leftlen + rightlen;
1713 }
1714
1715 void OutBuffer::spread(unsigned offset, unsigned nbytes)
1716 {
1717 reserve(nbytes);
1718 memmove(data + offset + nbytes, data + offset,
1719 this->offset - offset);
1720 this->offset += nbytes;
1721 }
1722
1723 /****************************************
1724 * Returns: offset + nbytes
1725 */
1726
1727 unsigned OutBuffer::insert(unsigned offset, const void *p, unsigned nbytes)
1728 {
1729 spread(offset, nbytes);
1730 memmove(data + offset, p, nbytes);
1731 return offset + nbytes;
1732 }
1733
1734 void OutBuffer::remove(unsigned offset, unsigned nbytes)
1735 {
1736 memmove(data + offset, data + offset + nbytes, this->offset - (offset + nbytes));
1737 this->offset -= nbytes;
1738 }
1739
1740 char *OutBuffer::toChars()
1741 {
1742 writeByte(0);
1743 return (char *)data;
1744 }
1745
1746 /********************************* Bits ****************************/
1747
1748 Bits::Bits()
1749 {
1750 data = NULL;
1751 bitdim = 0;
1752 allocdim = 0;
1753 }
1754
1755 Bits::~Bits()
1756 {
1757 mem.free(data);
1758 }
1759
1760 void Bits::mark()
1761 {
1762 mem.mark(data);
1763 }
1764
1765 void Bits::resize(unsigned bitdim)
1766 {
1767 unsigned allocdim;
1768 unsigned mask;
1769
1770 allocdim = (bitdim + 31) / 32;
1771 data = (unsigned *)mem.realloc(data, allocdim * sizeof(data[0]));
1772 if (this->allocdim < allocdim)
1773 memset(data + this->allocdim, 0, (allocdim - this->allocdim) * sizeof(data[0]));
1774
1775 // Clear other bits in last word
1776 mask = (1 << (bitdim & 31)) - 1;
1777 if (mask)
1778 data[allocdim - 1] &= ~mask;
1779
1780 this->bitdim = bitdim;
1781 this->allocdim = allocdim;
1782 }
1783
1784 void Bits::set(unsigned bitnum)
1785 {
1786 data[bitnum / 32] |= 1 << (bitnum & 31);
1787 }
1788
1789 void Bits::clear(unsigned bitnum)
1790 {
1791 data[bitnum / 32] &= ~(1 << (bitnum & 31));
1792 }
1793
1794 int Bits::test(unsigned bitnum)
1795 {
1796 return data[bitnum / 32] & (1 << (bitnum & 31));
1797 }
1798
1799 void Bits::set()
1800 { unsigned mask;
1801
1802 memset(data, ~0, allocdim * sizeof(data[0]));
1803
1804 // Clear other bits in last word
1805 mask = (1 << (bitdim & 31)) - 1;
1806 if (mask)
1807 data[allocdim - 1] &= mask;
1808 }
1809
1810 void Bits::clear()
1811 {
1812 memset(data, 0, allocdim * sizeof(data[0]));
1813 }
1814
1815 void Bits::copy(Bits *from)
1816 {
1817 assert(bitdim == from->bitdim);
1818 memcpy(data, from->data, allocdim * sizeof(data[0]));
1819 }
1820
1821 Bits *Bits::clone()
1822 {
1823 Bits *b;
1824
1825 b = new Bits();
1826 b->resize(bitdim);
1827 b->copy(this);
1828 return b;
1829 }
1830
1831 void Bits::sub(Bits *b)
1832 {
1833 unsigned u;
1834
1835 for (u = 0; u < allocdim; u++)
1836 data[u] &= ~b->data[u];
1837 }
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852