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