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