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 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