| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | #include "master.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* 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. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void init_c_io(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-01-18 19:43:14 -05: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); | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void io_error(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-10-15 19:59:35 -04:00
										 |  |  | #ifndef WINCE
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 	if(errno == EINTR) | 
					
						
							|  |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2007-10-15 19:59:35 -04:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	CELL error = tag_object(from_char_string(strerror(errno))); | 
					
						
							|  |  |  | 	general_error(ERROR_IO,error,F,NULL); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-13 04:20:34 -05:00
										 |  |  | void primitive_fopen(void) | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | { | 
					
						
							|  |  |  | 	char *mode = unbox_char_string(); | 
					
						
							|  |  |  | 	REGISTER_C_STRING(mode); | 
					
						
							|  |  |  | 	char *path = unbox_char_string(); | 
					
						
							|  |  |  | 	UNREGISTER_C_STRING(mode); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for(;;) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		FILE *file = fopen(path,mode); | 
					
						
							|  |  |  | 		if(file == NULL) | 
					
						
							|  |  |  | 			io_error(); | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			box_alien(file); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-13 04:20:34 -05:00
										 |  |  | void primitive_fgetc(void) | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | { | 
					
						
							|  |  |  | 	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; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-13 04:20:34 -05:00
										 |  |  | void primitive_fread(void) | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | { | 
					
						
							|  |  |  | 	FILE* file = unbox_alien(); | 
					
						
							|  |  |  | 	CELL size = unbox_array_size(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(size == 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		dpush(tag_object(allot_string(0,0))); | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	F_BYTE_ARRAY *buf = allot_byte_array(size); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for(;;) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		int c = fread(buf + 1,1,size,file); | 
					
						
							|  |  |  | 		if(c <= 0) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if(feof(file)) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				dpush(F); | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				io_error(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2008-03-06 16:58:05 -05:00
										 |  |  | 			if(c != size) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				REGISTER_UNTAGGED(buf); | 
					
						
							|  |  |  | 				F_BYTE_ARRAY *new_buf = allot_byte_array(c); | 
					
						
							|  |  |  | 				UNREGISTER_UNTAGGED(buf); | 
					
						
							|  |  |  | 				memcpy(new_buf + 1, buf + 1,c); | 
					
						
							|  |  |  | 				buf = new_buf; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			dpush(tag_object(buf)); | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-13 04:20:34 -05:00
										 |  |  | void primitive_fputc(void) | 
					
						
							| 
									
										
										
										
											2008-03-06 16:58:05 -05:00
										 |  |  | { | 
					
						
							|  |  |  | 	FILE *file = unbox_alien(); | 
					
						
							|  |  |  | 	F_FIXNUM ch = to_fixnum(dpop()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for(;;) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if(fputc(ch,file) == EOF) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			io_error(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* Still here? EINTR */ | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-13 04:20:34 -05:00
										 |  |  | void primitive_fwrite(void) | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-03-06 16:58:05 -05:00
										 |  |  | 	FILE *file = unbox_alien(); | 
					
						
							|  |  |  | 	F_BYTE_ARRAY *text = untag_byte_array(dpop()); | 
					
						
							|  |  |  | 	F_FIXNUM length = array_capacity(text); | 
					
						
							|  |  |  | 	char *string = (char *)(text + 1); | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-03-06 16:58:05 -05:00
										 |  |  | 	if(length == 0) | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 		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; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-13 04:20:34 -05:00
										 |  |  | void primitive_fflush(void) | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | { | 
					
						
							|  |  |  | 	FILE *file = unbox_alien(); | 
					
						
							|  |  |  | 	for(;;) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if(fflush(file) == EOF) | 
					
						
							|  |  |  | 			io_error(); | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-13 04:20:34 -05:00
										 |  |  | void primitive_fclose(void) | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | { | 
					
						
							|  |  |  | 	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. */ | 
					
						
							|  |  |  | int err_no(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return errno; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-03-21 15:53:11 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | void clear_err_no(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	errno = 0; | 
					
						
							|  |  |  | } |