| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | #include "master.hpp"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 02:46:13 -04:00
										 |  |  | namespace factor | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | /* Simple wrappers for ANSI C I/O functions, used for bootstrapping.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Note the ugly loop logic in almost every function; we have to handle EINTR | 
					
						
							|  |  |  | and restart the operation if the system call was interrupted. Naive | 
					
						
							|  |  |  | applications don't do this, but then they quickly fail if one enables | 
					
						
							|  |  |  | itimer()s or other signals. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The Factor library provides platform-specific code for Unix and Windows | 
					
						
							|  |  |  | with many more capabilities so these words are not usually used in | 
					
						
							|  |  |  | normal operation. */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-05 12:33:35 -04:00
										 |  |  | void init_c_io() | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	userenv[STDIN_ENV] = allot_alien(F,(cell)stdin); | 
					
						
							|  |  |  | 	userenv[STDOUT_ENV] = allot_alien(F,(cell)stdout); | 
					
						
							|  |  |  | 	userenv[STDERR_ENV] = allot_alien(F,(cell)stderr); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-05 12:33:35 -04:00
										 |  |  | void io_error() | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							|  |  |  | #ifndef WINCE
 | 
					
						
							|  |  |  | 	if(errno == EINTR) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-02 14:45:38 -04:00
										 |  |  | 	general_error(ERROR_IO,tag_fixnum(errno),F,NULL); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 02:00:30 -04:00
										 |  |  | PRIMITIVE(fopen) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	gc_root<byte_array> mode(dpop()); | 
					
						
							|  |  |  | 	gc_root<byte_array> path(dpop()); | 
					
						
							| 
									
										
										
										
											2009-05-02 14:45:38 -04:00
										 |  |  | 	mode.untag_check(); | 
					
						
							|  |  |  | 	path.untag_check(); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	for(;;) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-05-02 14:45:38 -04:00
										 |  |  | 		FILE *file = fopen((char *)(path.untagged() + 1), | 
					
						
							|  |  |  | 				   (char *)(mode.untagged() + 1)); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 		if(file == NULL) | 
					
						
							|  |  |  | 			io_error(); | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			box_alien(file); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 02:00:30 -04:00
										 |  |  | PRIMITIVE(fgetc) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							|  |  |  | 	FILE *file = (FILE *)unbox_alien(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for(;;) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		int c = fgetc(file); | 
					
						
							|  |  |  | 		if(c == EOF) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if(feof(file)) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				dpush(F); | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				io_error(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			dpush(tag_fixnum(c)); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 02:00:30 -04:00
										 |  |  | PRIMITIVE(fread) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							|  |  |  | 	FILE *file = (FILE *)unbox_alien(); | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	fixnum size = unbox_array_size(); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if(size == 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 		dpush(tag<string>(allot_string(0,0))); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	gc_root<byte_array> buf(allot_array_internal<byte_array>(size)); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	for(;;) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-05-02 10:19:09 -04:00
										 |  |  | 		int c = fread(buf.untagged() + 1,1,size,file); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 		if(c <= 0) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if(feof(file)) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				dpush(F); | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				io_error(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if(c != size) | 
					
						
							|  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 				byte_array *new_buf = allot_byte_array(c); | 
					
						
							| 
									
										
										
										
											2009-05-02 10:19:09 -04:00
										 |  |  | 				memcpy(new_buf + 1, buf.untagged() + 1,c); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 				buf = new_buf; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-05-02 10:19:09 -04:00
										 |  |  | 			dpush(buf.value()); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 02:00:30 -04:00
										 |  |  | PRIMITIVE(fputc) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							|  |  |  | 	FILE *file = (FILE *)unbox_alien(); | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	fixnum ch = to_fixnum(dpop()); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	for(;;) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if(fputc(ch,file) == EOF) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			io_error(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* Still here? EINTR */ | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 02:00:30 -04:00
										 |  |  | PRIMITIVE(fwrite) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							|  |  |  | 	FILE *file = (FILE *)unbox_alien(); | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	byte_array *text = untag_check<byte_array>(dpop()); | 
					
						
							|  |  |  | 	cell length = array_capacity(text); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	char *string = (char *)(text + 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(length == 0) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for(;;) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		size_t written = fwrite(string,1,length,file); | 
					
						
							|  |  |  | 		if(written == length) | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if(feof(file)) | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				io_error(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* Still here? EINTR */ | 
					
						
							|  |  |  | 			length -= written; | 
					
						
							|  |  |  | 			string += written; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 02:00:30 -04:00
										 |  |  | PRIMITIVE(fseek) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							|  |  |  | 	int whence = to_fixnum(dpop()); | 
					
						
							|  |  |  | 	FILE *file = (FILE *)unbox_alien(); | 
					
						
							|  |  |  | 	off_t offset = to_signed_8(dpop()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch(whence) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	case 0: whence = SEEK_SET; break; | 
					
						
							|  |  |  | 	case 1: whence = SEEK_CUR; break; | 
					
						
							|  |  |  | 	case 2: whence = SEEK_END; break; | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		critical_error("Bad value for whence",whence); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(FSEEK(file,offset,whence) == -1) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		io_error(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* Still here? EINTR */ | 
					
						
							|  |  |  | 		critical_error("Don't know what to do; EINTR from fseek()?",0); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 02:00:30 -04:00
										 |  |  | PRIMITIVE(fflush) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							|  |  |  | 	FILE *file = (FILE *)unbox_alien(); | 
					
						
							|  |  |  | 	for(;;) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if(fflush(file) == EOF) | 
					
						
							|  |  |  | 			io_error(); | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 02:00:30 -04:00
										 |  |  | PRIMITIVE(fclose) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							|  |  |  | 	FILE *file = (FILE *)unbox_alien(); | 
					
						
							|  |  |  | 	for(;;) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if(fclose(file) == EOF) | 
					
						
							|  |  |  | 			io_error(); | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* This function is used by FFI I/O. Accessing the errno global directly is
 | 
					
						
							|  |  |  | not portable, since on some libc's errno is not a global but a funky macro that | 
					
						
							|  |  |  | reads thread-local storage. */ | 
					
						
							| 
									
										
										
										
											2009-05-05 12:33:35 -04:00
										 |  |  | VM_C_API int err_no() | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							|  |  |  | 	return errno; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-05 12:33:35 -04:00
										 |  |  | VM_C_API void clear_err_no() | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							|  |  |  | 	errno = 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-05-04 02:46:13 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | } |