xref: /illumos-gate/usr/src/cmd/make/lib/mksh/read.cc (revision e7afc443)
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  */
60 Boolean		make_state_locked;
61 Source
get_next_block_fn(Source source)62 get_next_block_fn(Source source)
63 {
64 	off_t		to_read;
65 	int		length;
66 	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