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 * @(#)read.cc 1.11 06/12/12
27 */
28
29 #pragma ident "@(#)read.cc 1.11 06/12/12"
30
31 /*
32 * read.c
33 *
34 * This file contains the makefile reader.
35 */
36
37 /*
38 * Included files
39 */
40 #include <mksh/misc.h> /* retmem() */
41 #include <mksh/read.h>
42 #include <mksdmsi18n/mksdmsi18n.h>
43 #include <sys/uio.h> /* read() */
44 #include <unistd.h> /* close(), unlink(), read() */
45
46 #define STRING_LEN_TO_CONVERT (8*1024)
47
48 /*
49 * get_next_block_fn(source)
50 *
51 * Will get the next block of text to read either
52 * by popping one source bVSIZEOFlock of the stack of Sources
53 * or by reading some more from the makefile.
54 *
55 * Return value:
56 * The new source block to read from
57 *
58 * Parameters:
59 * source The old source block
60 *
61 * Global variables used:
62 * file_being_read The name of the current file, error msg
63 */
64 Boolean make_state_locked;
65 Source
66 get_next_block_fn(register Source source)
67 {
68 register off_t to_read;
69 register int length;
70 register size_t num_wc_chars;
71 char ch_save;
72 char *ptr;
73
74 if (source == NULL) {
75 return NULL;
76 }
77 if ((source->fd < 0) ||
78 ((source->bytes_left_in_file <= 0) &&
79 (source->inp_buf_ptr >= source->inp_buf_end))) {
80 /* We can't read from the makefile, so pop the source block */
81 if (source->fd > 2) {
82 (void) close(source->fd);
83 if (make_state_lockfile != NULL) {
84 (void) unlink(make_state_lockfile);
85 retmem_mb(make_state_lockfile);
86 make_state_lockfile = NULL;
87 make_state_locked = false;
88 }
89 }
90 if (source->string.free_after_use &&
91 (source->string.buffer.start != NULL)) {
92 retmem(source->string.buffer.start);
93 source->string.buffer.start = NULL;
94 }
95 if (source->inp_buf != NULL) {
96 retmem_mb(source->inp_buf);
97 source->inp_buf = NULL;
98 }
99 source = source->previous;
100 if (source != NULL) {
101 source->error_converting = false;
102 }
103 return source;
104 }
105 if (source->bytes_left_in_file > 0) {
106 /*
107 * Read the whole makefile.
108 * Hopefully the kernel managed to prefetch the stuff.
109 */
110 to_read = source->bytes_left_in_file;
111 source->inp_buf_ptr = source->inp_buf = getmem(to_read + 1);
112 source->inp_buf_end = source->inp_buf + to_read;
113 length = read(source->fd, source->inp_buf, (unsigned int) to_read);
114 if (length != to_read) {
115 WCSTOMBS(mbs_buffer, file_being_read);
116 if (length == 0) {
117 fatal_mksh(catgets(libmksdmsi18n_catd, 1, 140, "Error reading `%s': Premature EOF"),
118 mbs_buffer);
119 } else {
120 fatal_mksh(catgets(libmksdmsi18n_catd, 1, 141, "Error reading `%s': %s"),
121 mbs_buffer,
122 errmsg(errno));
123 }
124 }
125 *source->inp_buf_end = nul_char;
126 source->bytes_left_in_file = 0;
127 }
128 /*
129 * Try to convert the next piece.
130 */
131 ptr = source->inp_buf_ptr + STRING_LEN_TO_CONVERT;
132 if (ptr > source->inp_buf_end) {
133 ptr = source->inp_buf_end;
134 }
135 for (num_wc_chars = 0; ptr > source->inp_buf_ptr; ptr--) {
136 ch_save = *ptr;
137 *ptr = nul_char;
138 num_wc_chars = mbstowcs(source->string.text.end,
139 source->inp_buf_ptr,
140 STRING_LEN_TO_CONVERT);
141 *ptr = ch_save;
142 if (num_wc_chars != (size_t)-1) {
143 break;
144 }
145 }
146
147 if ((int) num_wc_chars == (size_t)-1) {
148 source->error_converting = true;
149 return source;
150 }
151
152 source->error_converting = false;
153 source->inp_buf_ptr = ptr;
154 source->string.text.end += num_wc_chars;
155 *source->string.text.end = 0;
156
157 if (source->inp_buf_ptr >= source->inp_buf_end) {
158 if (*(source->string.text.end - 1) != (int) newline_char) {
159 WCSTOMBS(mbs_buffer, file_being_read);
160 warning_mksh(catgets(libmksdmsi18n_catd, 1, 142, "newline is not last character in file %s"),
161 mbs_buffer);
162 *source->string.text.end++ = (int) newline_char;
163 *source->string.text.end = (int) nul_char;
164 *source->string.buffer.end++;
165 }
166 if (source->inp_buf != NULL) {
167 retmem_mb(source->inp_buf);
168 source->inp_buf = NULL;
169 }
170 }
171 return source;
172 }
173
174