1 // Copyright 2011 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 #include <stdarg.h> 29 30 #include "v8.h" 31 32 #include "platform.h" 33 34 #include "sys/stat.h" 35 36 namespace v8 { 37 namespace internal { 38 39 40 void PrintF(const char* format, ...) { 41 va_list arguments; 42 va_start(arguments, format); 43 OS::VPrint(format, arguments); 44 va_end(arguments); 45 } 46 47 48 void PrintF(FILE* out, const char* format, ...) { 49 va_list arguments; 50 va_start(arguments, format); 51 OS::VFPrint(out, format, arguments); 52 va_end(arguments); 53 } 54 55 56 void PrintPID(const char* format, ...) { 57 OS::Print("[%d] ", OS::GetCurrentProcessId()); 58 va_list arguments; 59 va_start(arguments, format); 60 OS::VPrint(format, arguments); 61 va_end(arguments); 62 } 63 64 65 void Flush(FILE* out) { 66 fflush(out); 67 } 68 69 70 char* ReadLine(const char* prompt) { 71 char* result = NULL; 72 char line_buf[256]; 73 int offset = 0; 74 bool keep_going = true; 75 fprintf(stdout, "%s", prompt); 76 fflush(stdout); 77 while (keep_going) { 78 if (fgets(line_buf, sizeof(line_buf), stdin) == NULL) { 79 // fgets got an error. Just give up. 80 if (result != NULL) { 81 DeleteArray(result); 82 } 83 return NULL; 84 } 85 int len = StrLength(line_buf); 86 if (len > 1 && 87 line_buf[len - 2] == '\\' && 88 line_buf[len - 1] == '\n') { 89 // When we read a line that ends with a "\" we remove the escape and 90 // append the remainder. 91 line_buf[len - 2] = '\n'; 92 line_buf[len - 1] = 0; 93 len -= 1; 94 } else if ((len > 0) && (line_buf[len - 1] == '\n')) { 95 // Since we read a new line we are done reading the line. This 96 // will exit the loop after copying this buffer into the result. 97 keep_going = false; 98 } 99 if (result == NULL) { 100 // Allocate the initial result and make room for the terminating '\0' 101 result = NewArray<char>(len + 1); 102 } else { 103 // Allocate a new result with enough room for the new addition. 104 int new_len = offset + len + 1; 105 char* new_result = NewArray<char>(new_len); 106 // Copy the existing input into the new array and set the new 107 // array as the result. 108 OS::MemCopy(new_result, result, offset * kCharSize); 109 DeleteArray(result); 110 result = new_result; 111 } 112 // Copy the newly read line into the result. 113 OS::MemCopy(result + offset, line_buf, len * kCharSize); 114 offset += len; 115 } 116 ASSERT(result != NULL); 117 result[offset] = '\0'; 118 return result; 119 } 120 121 122 char* ReadCharsFromFile(FILE* file, 123 int* size, 124 int extra_space, 125 bool verbose, 126 const char* filename) { 127 if (file == NULL || fseek(file, 0, SEEK_END) != 0) { 128 if (verbose) { 129 OS::PrintError("Cannot read from file %s.\n", filename); 130 } 131 return NULL; 132 } 133 134 // Get the size of the file and rewind it. 135 *size = ftell(file); 136 rewind(file); 137 138 char* result = NewArray<char>(*size + extra_space); 139 for (int i = 0; i < *size && feof(file) == 0;) { 140 int read = static_cast<int>(fread(&result[i], 1, *size - i, file)); 141 if (read != (*size - i) && ferror(file) != 0) { 142 fclose(file); 143 DeleteArray(result); 144 return NULL; 145 } 146 i += read; 147 } 148 return result; 149 } 150 151 152 char* ReadCharsFromFile(const char* filename, 153 int* size, 154 int extra_space, 155 bool verbose) { 156 FILE* file = OS::FOpen(filename, "rb"); 157 char* result = ReadCharsFromFile(file, size, extra_space, verbose, filename); 158 if (file != NULL) fclose(file); 159 return result; 160 } 161 162 163 byte* ReadBytes(const char* filename, int* size, bool verbose) { 164 char* chars = ReadCharsFromFile(filename, size, 0, verbose); 165 return reinterpret_cast<byte*>(chars); 166 } 167 168 169 static Vector<const char> SetVectorContents(char* chars, 170 int size, 171 bool* exists) { 172 if (!chars) { 173 *exists = false; 174 return Vector<const char>::empty(); 175 } 176 chars[size] = '\0'; 177 *exists = true; 178 return Vector<const char>(chars, size); 179 } 180 181 182 Vector<const char> ReadFile(const char* filename, 183 bool* exists, 184 bool verbose) { 185 int size; 186 char* result = ReadCharsFromFile(filename, &size, 1, verbose); 187 return SetVectorContents(result, size, exists); 188 } 189 190 191 Vector<const char> ReadFile(FILE* file, 192 bool* exists, 193 bool verbose) { 194 int size; 195 char* result = ReadCharsFromFile(file, &size, 1, verbose, ""); 196 return SetVectorContents(result, size, exists); 197 } 198 199 200 int WriteCharsToFile(const char* str, int size, FILE* f) { 201 int total = 0; 202 while (total < size) { 203 int write = static_cast<int>(fwrite(str, 1, size - total, f)); 204 if (write == 0) { 205 return total; 206 } 207 total += write; 208 str += write; 209 } 210 return total; 211 } 212 213 214 int AppendChars(const char* filename, 215 const char* str, 216 int size, 217 bool verbose) { 218 FILE* f = OS::FOpen(filename, "ab"); 219 if (f == NULL) { 220 if (verbose) { 221 OS::PrintError("Cannot open file %s for writing.\n", filename); 222 } 223 return 0; 224 } 225 int written = WriteCharsToFile(str, size, f); 226 fclose(f); 227 return written; 228 } 229 230 231 int WriteChars(const char* filename, 232 const char* str, 233 int size, 234 bool verbose) { 235 FILE* f = OS::FOpen(filename, "wb"); 236 if (f == NULL) { 237 if (verbose) { 238 OS::PrintError("Cannot open file %s for writing.\n", filename); 239 } 240 return 0; 241 } 242 int written = WriteCharsToFile(str, size, f); 243 fclose(f); 244 return written; 245 } 246 247 248 int WriteBytes(const char* filename, 249 const byte* bytes, 250 int size, 251 bool verbose) { 252 const char* str = reinterpret_cast<const char*>(bytes); 253 return WriteChars(filename, str, size, verbose); 254 } 255 256 257 258 void StringBuilder::AddFormatted(const char* format, ...) { 259 va_list arguments; 260 va_start(arguments, format); 261 AddFormattedList(format, arguments); 262 va_end(arguments); 263 } 264 265 266 void StringBuilder::AddFormattedList(const char* format, va_list list) { 267 ASSERT(!is_finalized() && position_ <= buffer_.length()); 268 int n = OS::VSNPrintF(buffer_ + position_, format, list); 269 if (n < 0 || n >= (buffer_.length() - position_)) { 270 position_ = buffer_.length(); 271 } else { 272 position_ += n; 273 } 274 } 275 276 } } // namespace v8::internal 277