1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26
27/*
28 *	read.c
29 *
30 *	This file contains the makefile reader.
31 */
32
33/*
34 * Included files
35 */
36#include <mksh/misc.h>		/* retmem() */
37#include <mksh/read.h>
38#include <sys/uio.h>		/* read() */
39#include <unistd.h>		/* close(), unlink(), read() */
40#include <libintl.h>
41
42#define	STRING_LEN_TO_CONVERT	(8*1024)
43
44/*
45 *	get_next_block_fn(source)
46 *
47 *	Will get the next block of text to read either
48 *	by popping one source bVSIZEOFlock of the stack of Sources
49 *	or by reading some more from the makefile.
50 *
51 *	Return value:
52 *				The new source block to read from
53 *
54 *	Parameters:
55 *		source		The old source block
56 *
57 *	Global variables used:
58 *		file_being_read	The name of the current file, error msg
59 */
60Boolean		make_state_locked;
61Source
62get_next_block_fn(register Source source)
63{
64	register off_t		to_read;
65	register int		length;
66	register size_t		num_wc_chars;
67	char			ch_save;
68	char			*ptr;
69
70	if (source == NULL) {
71		return NULL;
72	}
73	if ((source->fd < 0) ||
74		((source->bytes_left_in_file <= 0) &&
75			(source->inp_buf_ptr >= source->inp_buf_end))) {
76		/* We can't read from the makefile, so pop the source block */
77		if (source->fd > 2) {
78			(void) close(source->fd);
79			if (make_state_lockfile != NULL) {
80				(void) unlink(make_state_lockfile);
81				retmem_mb(make_state_lockfile);
82				make_state_lockfile = NULL;
83				make_state_locked = false;
84			}
85		}
86		if (source->string.free_after_use &&
87		    (source->string.buffer.start != NULL)) {
88			retmem(source->string.buffer.start);
89			source->string.buffer.start = NULL;
90		}
91		if (source->inp_buf != NULL) {
92			retmem_mb(source->inp_buf);
93			source->inp_buf = NULL;
94		}
95		source = source->previous;
96		if (source != NULL) {
97			source->error_converting = false;
98		}
99		return source;
100	}
101	if (source->bytes_left_in_file > 0) {
102	/*
103	 * Read the whole makefile.
104	 * Hopefully the kernel managed to prefetch the stuff.
105	 */
106		to_read = source->bytes_left_in_file;
107	 	source->inp_buf_ptr = source->inp_buf = getmem(to_read + 1);
108		source->inp_buf_end = source->inp_buf + to_read;
109		length = read(source->fd, source->inp_buf, (unsigned int) to_read);
110		if (length != to_read) {
111			WCSTOMBS(mbs_buffer, file_being_read);
112			if (length == 0) {
113				fatal_mksh(gettext("Error reading `%s': Premature EOF"),
114				      mbs_buffer);
115			} else {
116				fatal_mksh(gettext("Error reading `%s': %s"),
117				      mbs_buffer,
118				      errmsg(errno));
119			}
120		}
121		*source->inp_buf_end = nul_char;
122		source->bytes_left_in_file = 0;
123	}
124	/*
125	 * Try to convert the next piece.
126	 */
127	ptr = source->inp_buf_ptr + STRING_LEN_TO_CONVERT;
128	if (ptr > source->inp_buf_end) {
129		ptr = source->inp_buf_end;
130	}
131	for (num_wc_chars = 0; ptr > source->inp_buf_ptr; ptr--) {
132		ch_save = *ptr;
133		*ptr = nul_char;
134		num_wc_chars = mbstowcs(source->string.text.end,
135					source->inp_buf_ptr,
136					STRING_LEN_TO_CONVERT);
137		*ptr = ch_save;
138		if (num_wc_chars != (size_t)-1) {
139			break;
140		}
141	}
142
143	if ((int) num_wc_chars == (size_t)-1) {
144		source->error_converting = true;
145		return source;
146	}
147
148	source->error_converting = false;
149	source->inp_buf_ptr = ptr;
150	source->string.text.end += num_wc_chars;
151	*source->string.text.end = 0;
152
153	if (source->inp_buf_ptr >= source->inp_buf_end) {
154		if (*(source->string.text.end - 1) != (int) newline_char) {
155			WCSTOMBS(mbs_buffer, file_being_read);
156			warning_mksh(gettext("newline is not last character in file %s"),
157					     mbs_buffer);
158			*source->string.text.end++ = (int) newline_char;
159			*source->string.text.end = (int) nul_char;
160			*source->string.buffer.end++;
161		}
162		if (source->inp_buf != NULL) {
163			retmem_mb(source->inp_buf);
164			source->inp_buf = NULL;
165		}
166	}
167	return source;
168}
169
170
171