xref: /illumos-gate/usr/src/cmd/sort/streams_wide.c (revision 101e15b5)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5bc37da3aSnakanon  * Common Development and Distribution License (the "License").
6bc37da3aSnakanon  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22bc37da3aSnakanon  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include "streams_wide.h"
277c478bd9Sstevel@tonic-gate #include "streams_common.h"
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate #define	WIDE_VBUF_SIZE	(64 * KILOBYTE)
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate #define	SHELF_OCCUPIED	1
327c478bd9Sstevel@tonic-gate #define	SHELF_VACANT	0
337c478bd9Sstevel@tonic-gate static int shelf = SHELF_VACANT;
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate /*
367c478bd9Sstevel@tonic-gate  * Wide character streams implementation
377c478bd9Sstevel@tonic-gate  *
387c478bd9Sstevel@tonic-gate  *   The wide character streams implementation is, for the most part, a
397c478bd9Sstevel@tonic-gate  *   reimplementation of the stdio streams implementation, using wide character
407c478bd9Sstevel@tonic-gate  *   string routines.  However, fgetws(3C) retains the newline that fgets(3C)
417c478bd9Sstevel@tonic-gate  *   discards while reading a complete line.  As a result, the wide character
427c478bd9Sstevel@tonic-gate  *   routines need to guard against coincidental exhaustion of the buffer, as
437c478bd9Sstevel@tonic-gate  *   well as overwriting the end-of-line character and correcting the
447c478bd9Sstevel@tonic-gate  *   l_data_length field.
457c478bd9Sstevel@tonic-gate  */
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate static int
stream_wide_prime(stream_t * str)487c478bd9Sstevel@tonic-gate stream_wide_prime(stream_t *str)
497c478bd9Sstevel@tonic-gate {
507c478bd9Sstevel@tonic-gate 	stream_buffered_file_t *BF = &(str->s_type.BF);
517c478bd9Sstevel@tonic-gate 	wchar_t *current_position;
527c478bd9Sstevel@tonic-gate 	wchar_t *end_of_buffer;
537c478bd9Sstevel@tonic-gate 	wchar_t *next_nl;
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate 	ASSERT(!(str->s_status & STREAM_OUTPUT));
567c478bd9Sstevel@tonic-gate 	ASSERT(str->s_status & STREAM_OPEN);
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate 	if (str->s_status & STREAM_INSTANT && (str->s_buffer == NULL)) {
597c478bd9Sstevel@tonic-gate 		str->s_buffer = xzmap(0, WIDE_VBUF_SIZE, PROT_READ |
607c478bd9Sstevel@tonic-gate 		    PROT_WRITE, MAP_PRIVATE, 0);
617c478bd9Sstevel@tonic-gate 		if (str->s_buffer == MAP_FAILED)
627c478bd9Sstevel@tonic-gate 			die(EMSG_MMAP);
637c478bd9Sstevel@tonic-gate 		str->s_buffer_size = WIDE_VBUF_SIZE;
647c478bd9Sstevel@tonic-gate 	}
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate 	ASSERT(str->s_buffer != NULL);
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate 	if (stream_is_primed(str)) {
697c478bd9Sstevel@tonic-gate 		int shelf_state = shelf;
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate 		ASSERT(str->s_current.l_data_length >= -1);
727c478bd9Sstevel@tonic-gate 		(void) memcpy(str->s_buffer, str->s_current.l_data.wp,
737c478bd9Sstevel@tonic-gate 		    (str->s_current.l_data_length + 1) * sizeof (wchar_t));
747c478bd9Sstevel@tonic-gate 		str->s_current.l_data.wp = str->s_buffer;
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate 		if ((str->s_current.l_data_length == -1 ||
777c478bd9Sstevel@tonic-gate 		    shelf_state == SHELF_OCCUPIED ||
787c478bd9Sstevel@tonic-gate 		    *(str->s_current.l_data.wp +
797c478bd9Sstevel@tonic-gate 		    str->s_current.l_data_length) != L'\0') &&
807c478bd9Sstevel@tonic-gate 		    SOP_FETCH(str) == NEXT_LINE_INCOMPLETE &&
817c478bd9Sstevel@tonic-gate 		    shelf_state == SHELF_OCCUPIED)
827c478bd9Sstevel@tonic-gate 			die(EMSG_MEMORY);
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate 		return (PRIME_SUCCEEDED);
857c478bd9Sstevel@tonic-gate 	}
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate 	stream_set(str, STREAM_PRIMED);
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate 	current_position = (wchar_t *)str->s_buffer;
907c478bd9Sstevel@tonic-gate 	/*LINTED ALIGNMENT*/
917c478bd9Sstevel@tonic-gate 	end_of_buffer = (wchar_t *)((char *)str->s_buffer +
927c478bd9Sstevel@tonic-gate 	    str->s_buffer_size);
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate 	trip_eof(BF->s_fp);
957c478bd9Sstevel@tonic-gate 	if (!feof(BF->s_fp))
967c478bd9Sstevel@tonic-gate 		(void) fgetws(current_position, end_of_buffer
977c478bd9Sstevel@tonic-gate 		    - current_position, BF->s_fp);
987c478bd9Sstevel@tonic-gate 	else {
997c478bd9Sstevel@tonic-gate 		stream_set(str, STREAM_EOS_REACHED);
1007c478bd9Sstevel@tonic-gate 		stream_unset(str, STREAM_PRIMED);
1017c478bd9Sstevel@tonic-gate 		return (PRIME_FAILED_EMPTY_FILE);
1027c478bd9Sstevel@tonic-gate 	}
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate 	str->s_current.l_data.wp = current_position;
1057c478bd9Sstevel@tonic-gate 	next_nl = xmemwchar(current_position, L'\n', end_of_buffer -
1067c478bd9Sstevel@tonic-gate 	    current_position);
1077c478bd9Sstevel@tonic-gate 	if (next_nl == NULL) {
1087c478bd9Sstevel@tonic-gate 		warn(WMSG_NEWLINE_ADDED, str->s_filename);
1097c478bd9Sstevel@tonic-gate 		str->s_current.l_data_length = MIN(wslen(current_position),
1107c478bd9Sstevel@tonic-gate 		    end_of_buffer - current_position);
1117c478bd9Sstevel@tonic-gate 	} else {
1127c478bd9Sstevel@tonic-gate 		str->s_current.l_data_length = next_nl - current_position;
1137c478bd9Sstevel@tonic-gate 	}
1147c478bd9Sstevel@tonic-gate 	*(str->s_current.l_data.wp + str->s_current.l_data_length) = L'\0';
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate 	str->s_current.l_collate.wp = NULL;
1177c478bd9Sstevel@tonic-gate 	str->s_current.l_collate_length = 0;
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate 	__S(stats_incr_fetches());
1207c478bd9Sstevel@tonic-gate 	return (PRIME_SUCCEEDED);
1217c478bd9Sstevel@tonic-gate }
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate static ssize_t
stream_wide_fetch(stream_t * str)1247c478bd9Sstevel@tonic-gate stream_wide_fetch(stream_t *str)
1257c478bd9Sstevel@tonic-gate {
1267c478bd9Sstevel@tonic-gate 	ssize_t dist_to_buf_end;
1277c478bd9Sstevel@tonic-gate 	int ret_val;
1287c478bd9Sstevel@tonic-gate 	wchar_t *graft_pt;
1297c478bd9Sstevel@tonic-gate 	wchar_t *next_nl;
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate 	ASSERT(str->s_status & STREAM_OPEN);
1327c478bd9Sstevel@tonic-gate 	ASSERT((str->s_status & STREAM_EOS_REACHED) == 0);
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate 	graft_pt = str->s_current.l_data.wp + str->s_current.l_data_length + 1;
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate 	if (shelf == SHELF_VACANT)
1377c478bd9Sstevel@tonic-gate 		str->s_current.l_data.wp = graft_pt;
1387c478bd9Sstevel@tonic-gate 	else if (str->s_current.l_data_length > -1)
1397c478bd9Sstevel@tonic-gate 		graft_pt--;
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate 	dist_to_buf_end = str->s_buffer_size / sizeof (wchar_t) - (graft_pt -
1427c478bd9Sstevel@tonic-gate 	    (wchar_t *)str->s_buffer);
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate 	if (dist_to_buf_end <= 1) {
1457c478bd9Sstevel@tonic-gate 		str->s_current.l_data_length = -1;
1467c478bd9Sstevel@tonic-gate 		return (NEXT_LINE_INCOMPLETE);
1477c478bd9Sstevel@tonic-gate 	}
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate 	if (fgetws(graft_pt, dist_to_buf_end, str->s_type.BF.s_fp) == NULL) {
1507c478bd9Sstevel@tonic-gate 		if (feof(str->s_type.BF.s_fp))
1517c478bd9Sstevel@tonic-gate 			stream_set(str, STREAM_EOS_REACHED);
1527c478bd9Sstevel@tonic-gate 		else
1537c478bd9Sstevel@tonic-gate 			die(EMSG_READ, str->s_filename);
1547c478bd9Sstevel@tonic-gate 	}
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 	trip_eof(str->s_type.BF.s_fp);
1577c478bd9Sstevel@tonic-gate 	if ((next_nl = xmemwchar(str->s_current.l_data.wp, L'\n',
1587c478bd9Sstevel@tonic-gate 	    dist_to_buf_end)) == NULL) {
1597c478bd9Sstevel@tonic-gate 		str->s_current.l_data_length =
1607c478bd9Sstevel@tonic-gate 		    MIN(wslen(str->s_current.l_data.wp), dist_to_buf_end);
1617c478bd9Sstevel@tonic-gate 	} else {
1627c478bd9Sstevel@tonic-gate 		str->s_current.l_data_length = next_nl -
1637c478bd9Sstevel@tonic-gate 		    str->s_current.l_data.wp;
1647c478bd9Sstevel@tonic-gate 	}
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate 	str->s_current.l_collate_length = 0;
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate 	if (*(str->s_current.l_data.wp + str->s_current.l_data_length) !=
1697c478bd9Sstevel@tonic-gate 	    L'\n') {
1707c478bd9Sstevel@tonic-gate 		if (!feof(str->s_type.BF.s_fp)) {
1717c478bd9Sstevel@tonic-gate 			if (shelf == SHELF_OCCUPIED)
1727c478bd9Sstevel@tonic-gate 				die(EMSG_MEMORY);
1737c478bd9Sstevel@tonic-gate 
1747c478bd9Sstevel@tonic-gate 			shelf = SHELF_OCCUPIED;
1757c478bd9Sstevel@tonic-gate 			ret_val = NEXT_LINE_INCOMPLETE;
1767c478bd9Sstevel@tonic-gate 			__S(stats_incr_shelves());
1777c478bd9Sstevel@tonic-gate 		} else {
1787c478bd9Sstevel@tonic-gate 			stream_set(str, STREAM_EOS_REACHED);
1797c478bd9Sstevel@tonic-gate 			warn(WMSG_NEWLINE_ADDED, str->s_filename);
1807c478bd9Sstevel@tonic-gate 		}
1817c478bd9Sstevel@tonic-gate 	} else {
1827c478bd9Sstevel@tonic-gate 		shelf = SHELF_VACANT;
1837c478bd9Sstevel@tonic-gate 		ret_val = NEXT_LINE_COMPLETE;
1847c478bd9Sstevel@tonic-gate 		*(str->s_current.l_data.wp + str->s_current.l_data_length) =
1857c478bd9Sstevel@tonic-gate 		    L'\0';
1867c478bd9Sstevel@tonic-gate 		__S(stats_incr_fetches());
1877c478bd9Sstevel@tonic-gate 	}
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate 	return (ret_val);
1907c478bd9Sstevel@tonic-gate }
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate ssize_t
stream_wide_fetch_overwrite(stream_t * str)1937c478bd9Sstevel@tonic-gate stream_wide_fetch_overwrite(stream_t *str)
1947c478bd9Sstevel@tonic-gate {
1957c478bd9Sstevel@tonic-gate 	ssize_t dist_to_buf_end;
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate 	ASSERT(str->s_status & STREAM_OPEN);
1987c478bd9Sstevel@tonic-gate 	ASSERT((str->s_status & STREAM_EOS_REACHED) == 0);
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 	str->s_current.l_data.wp = str->s_buffer;
2017c478bd9Sstevel@tonic-gate 	dist_to_buf_end = str->s_buffer_size / sizeof (wchar_t);
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 	if (fgetws(str->s_current.l_data.wp, dist_to_buf_end,
2047c478bd9Sstevel@tonic-gate 	    str->s_type.BF.s_fp) == NULL) {
2057c478bd9Sstevel@tonic-gate 		if (feof(str->s_type.BF.s_fp))
2067c478bd9Sstevel@tonic-gate 			stream_set(str, STREAM_EOS_REACHED);
2077c478bd9Sstevel@tonic-gate 		else
2087c478bd9Sstevel@tonic-gate 			die(EMSG_READ, str->s_filename);
2097c478bd9Sstevel@tonic-gate 	}
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate 	trip_eof(str->s_type.BF.s_fp);
2127c478bd9Sstevel@tonic-gate 	str->s_current.l_data_length = wslen(str->s_current.l_data.wp) - 1;
2137c478bd9Sstevel@tonic-gate 	str->s_current.l_collate_length = 0;
2147c478bd9Sstevel@tonic-gate 
2157c478bd9Sstevel@tonic-gate 	if (str->s_current.l_data_length == -1 ||
2167c478bd9Sstevel@tonic-gate 	    *(str->s_current.l_data.wp + str->s_current.l_data_length) !=
2177c478bd9Sstevel@tonic-gate 	    L'\n') {
2187c478bd9Sstevel@tonic-gate 		if (!feof(str->s_type.BF.s_fp)) {
2197c478bd9Sstevel@tonic-gate 			die(EMSG_MEMORY);
2207c478bd9Sstevel@tonic-gate 		} else {
2217c478bd9Sstevel@tonic-gate 			stream_set(str, STREAM_EOS_REACHED);
2227c478bd9Sstevel@tonic-gate 			warn(WMSG_NEWLINE_ADDED, str->s_filename);
2237c478bd9Sstevel@tonic-gate 			str->s_current.l_data_length++;
2247c478bd9Sstevel@tonic-gate 		}
2257c478bd9Sstevel@tonic-gate 	}
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 	*(str->s_current.l_data.wp + str->s_current.l_data_length) = L'\0';
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate 	__S(stats_incr_fetches());
2307c478bd9Sstevel@tonic-gate 	return (NEXT_LINE_COMPLETE);
2317c478bd9Sstevel@tonic-gate }
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate static void
stream_wide_send_eol(stream_t * str)2347c478bd9Sstevel@tonic-gate stream_wide_send_eol(stream_t *str)
2357c478bd9Sstevel@tonic-gate {
2367c478bd9Sstevel@tonic-gate 	wchar_t w_crlf[2] = { L'\n', L'\0' };
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate 	ASSERT(str->s_status & STREAM_OPEN);
2397c478bd9Sstevel@tonic-gate 	ASSERT(str->s_status & STREAM_OUTPUT);
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate 	if (wxwrite(str->s_type.SF.s_fd, w_crlf) < 0)
2427c478bd9Sstevel@tonic-gate 		die(EMSG_WRITE, str->s_filename);
2437c478bd9Sstevel@tonic-gate }
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate static void
stream_wide_put_line(stream_t * str,line_rec_t * line)2467c478bd9Sstevel@tonic-gate stream_wide_put_line(stream_t *str, line_rec_t *line)
2477c478bd9Sstevel@tonic-gate {
2487c478bd9Sstevel@tonic-gate 	ASSERT(str->s_status & STREAM_OPEN);
2497c478bd9Sstevel@tonic-gate 	ASSERT(str->s_status & STREAM_OUTPUT);
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate 	if (line->l_data_length >= 0) {
2527c478bd9Sstevel@tonic-gate 		if (wxwrite(str->s_type.SF.s_fd, line->l_data.wp) >= 0) {
2537c478bd9Sstevel@tonic-gate 			stream_wide_send_eol(str);
2547c478bd9Sstevel@tonic-gate 			__S(stats_incr_puts());
2557c478bd9Sstevel@tonic-gate 		} else
2567c478bd9Sstevel@tonic-gate 			die(EMSG_WRITE, str->s_filename);
2577c478bd9Sstevel@tonic-gate 	}
258bc37da3aSnakanon 	safe_free(line->l_raw_collate.wp);
259bc37da3aSnakanon 	line->l_raw_collate.wp = NULL;
2607c478bd9Sstevel@tonic-gate }
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate void
stream_wide_put_line_unique(stream_t * str,line_rec_t * line)2637c478bd9Sstevel@tonic-gate stream_wide_put_line_unique(stream_t *str, line_rec_t *line)
2647c478bd9Sstevel@tonic-gate {
2657c478bd9Sstevel@tonic-gate 	static line_rec_t pvs;
2667c478bd9Sstevel@tonic-gate 	static size_t collate_buf_len;
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 	ASSERT(str->s_status & STREAM_OPEN);
2697c478bd9Sstevel@tonic-gate 	ASSERT(str->s_status & STREAM_OUTPUT);
2707c478bd9Sstevel@tonic-gate 
2717c478bd9Sstevel@tonic-gate 	if ((pvs.l_collate.sp == NULL ||
2727c478bd9Sstevel@tonic-gate 	    collated_wide(&pvs, line, 0, COLL_UNIQUE) != 0) &&
2737c478bd9Sstevel@tonic-gate 	    line->l_data_length >= 0) {
2747c478bd9Sstevel@tonic-gate 		stream_wide_put_line(str, line);
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate 		if (line->l_collate_length + sizeof (wchar_t) >
2777c478bd9Sstevel@tonic-gate 		    collate_buf_len) {
2787c478bd9Sstevel@tonic-gate 			pvs.l_collate.sp = safe_realloc(pvs.l_collate.sp,
2797c478bd9Sstevel@tonic-gate 			    line->l_collate_length + sizeof (wchar_t));
2807c478bd9Sstevel@tonic-gate 			collate_buf_len = line->l_collate_length +
2817c478bd9Sstevel@tonic-gate 			    sizeof (wchar_t);
2827c478bd9Sstevel@tonic-gate 		}
2837c478bd9Sstevel@tonic-gate 
2847c478bd9Sstevel@tonic-gate 		(void) memcpy(pvs.l_collate.sp, line->l_collate.sp,
2857c478bd9Sstevel@tonic-gate 		    line->l_collate_length);
2867c478bd9Sstevel@tonic-gate 		/* LINTED ALIGNMENT */
2877c478bd9Sstevel@tonic-gate 		*(wchar_t *)(pvs.l_collate.sp + line->l_collate_length) = L'\0';
2887c478bd9Sstevel@tonic-gate 		pvs.l_collate_length = line->l_collate_length;
2897c478bd9Sstevel@tonic-gate 	}
2907c478bd9Sstevel@tonic-gate }
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate static int
stream_wide_eos(stream_t * str)2937c478bd9Sstevel@tonic-gate stream_wide_eos(stream_t *str)
2947c478bd9Sstevel@tonic-gate {
2957c478bd9Sstevel@tonic-gate 	int retval = 0;
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate 	if (str == NULL || str->s_status & STREAM_EOS_REACHED)
2987c478bd9Sstevel@tonic-gate 		return (1);
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate 	trip_eof(str->s_type.BF.s_fp);
3017c478bd9Sstevel@tonic-gate 	if (feof(str->s_type.BF.s_fp) &&
3027c478bd9Sstevel@tonic-gate 	    shelf == SHELF_VACANT &&
3037c478bd9Sstevel@tonic-gate 	    str->s_current.l_collate_length != -1) {
3047c478bd9Sstevel@tonic-gate 		retval = 1;
3057c478bd9Sstevel@tonic-gate 		stream_set(str, STREAM_EOS_REACHED);
3067c478bd9Sstevel@tonic-gate 	}
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate 	return (retval);
3097c478bd9Sstevel@tonic-gate }
3107c478bd9Sstevel@tonic-gate 
3117c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3127c478bd9Sstevel@tonic-gate static void
stream_wide_release_line(stream_t * str)3137c478bd9Sstevel@tonic-gate stream_wide_release_line(stream_t *str)
3147c478bd9Sstevel@tonic-gate {
3157c478bd9Sstevel@tonic-gate }
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate const stream_ops_t stream_wide_ops = {
3187c478bd9Sstevel@tonic-gate 	stream_stdio_is_closable,
3197c478bd9Sstevel@tonic-gate 	stream_stdio_close,
3207c478bd9Sstevel@tonic-gate 	stream_wide_eos,
3217c478bd9Sstevel@tonic-gate 	stream_wide_fetch,
3227c478bd9Sstevel@tonic-gate 	stream_stdio_flush,
3237c478bd9Sstevel@tonic-gate 	stream_stdio_free,
3247c478bd9Sstevel@tonic-gate 	stream_stdio_open_for_write,
3257c478bd9Sstevel@tonic-gate 	stream_wide_prime,
3267c478bd9Sstevel@tonic-gate 	stream_wide_put_line,
3277c478bd9Sstevel@tonic-gate 	stream_wide_release_line,
3287c478bd9Sstevel@tonic-gate 	stream_wide_send_eol,
3297c478bd9Sstevel@tonic-gate 	stream_stdio_unlink
3307c478bd9Sstevel@tonic-gate };
331