1 // Copyright 2011 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <stdarg.h> 6 #include <sys/stat.h> 7 8 #include "src/v8.h" 9 10 #include "src/checks.h" 11 #include "src/platform.h" 12 #include "src/utils.h" 13 14 namespace v8 { 15 namespace internal { 16 17 18 SimpleStringBuilder::SimpleStringBuilder(int size) { 19 buffer_ = Vector<char>::New(size); 20 position_ = 0; 21 } 22 23 24 void SimpleStringBuilder::AddString(const char* s) { 25 AddSubstring(s, StrLength(s)); 26 } 27 28 29 void SimpleStringBuilder::AddSubstring(const char* s, int n) { 30 ASSERT(!is_finalized() && position_ + n <= buffer_.length()); 31 ASSERT(static_cast<size_t>(n) <= strlen(s)); 32 MemCopy(&buffer_[position_], s, n * kCharSize); 33 position_ += n; 34 } 35 36 37 void SimpleStringBuilder::AddPadding(char c, int count) { 38 for (int i = 0; i < count; i++) { 39 AddCharacter(c); 40 } 41 } 42 43 44 void SimpleStringBuilder::AddDecimalInteger(int32_t value) { 45 uint32_t number = static_cast<uint32_t>(value); 46 if (value < 0) { 47 AddCharacter('-'); 48 number = static_cast<uint32_t>(-value); 49 } 50 int digits = 1; 51 for (uint32_t factor = 10; digits < 10; digits++, factor *= 10) { 52 if (factor > number) break; 53 } 54 position_ += digits; 55 for (int i = 1; i <= digits; i++) { 56 buffer_[position_ - i] = '0' + static_cast<char>(number % 10); 57 number /= 10; 58 } 59 } 60 61 62 char* SimpleStringBuilder::Finalize() { 63 ASSERT(!is_finalized() && position_ <= buffer_.length()); 64 // If there is no space for null termination, overwrite last character. 65 if (position_ == buffer_.length()) { 66 position_--; 67 // Print ellipsis. 68 for (int i = 3; i > 0 && position_ > i; --i) buffer_[position_ - i] = '.'; 69 } 70 buffer_[position_] = '\0'; 71 // Make sure nobody managed to add a 0-character to the 72 // buffer while building the string. 73 ASSERT(strlen(buffer_.start()) == static_cast<size_t>(position_)); 74 position_ = -1; 75 ASSERT(is_finalized()); 76 return buffer_.start(); 77 } 78 79 80 void PrintF(const char* format, ...) { 81 va_list arguments; 82 va_start(arguments, format); 83 OS::VPrint(format, arguments); 84 va_end(arguments); 85 } 86 87 88 void PrintF(FILE* out, const char* format, ...) { 89 va_list arguments; 90 va_start(arguments, format); 91 OS::VFPrint(out, format, arguments); 92 va_end(arguments); 93 } 94 95 96 void PrintPID(const char* format, ...) { 97 OS::Print("[%d] ", OS::GetCurrentProcessId()); 98 va_list arguments; 99 va_start(arguments, format); 100 OS::VPrint(format, arguments); 101 va_end(arguments); 102 } 103 104 105 int SNPrintF(Vector<char> str, const char* format, ...) { 106 va_list args; 107 va_start(args, format); 108 int result = VSNPrintF(str, format, args); 109 va_end(args); 110 return result; 111 } 112 113 114 int VSNPrintF(Vector<char> str, const char* format, va_list args) { 115 return OS::VSNPrintF(str.start(), str.length(), format, args); 116 } 117 118 119 void StrNCpy(Vector<char> dest, const char* src, size_t n) { 120 OS::StrNCpy(dest.start(), dest.length(), src, n); 121 } 122 123 124 void Flush(FILE* out) { 125 fflush(out); 126 } 127 128 129 char* ReadLine(const char* prompt) { 130 char* result = NULL; 131 char line_buf[256]; 132 int offset = 0; 133 bool keep_going = true; 134 fprintf(stdout, "%s", prompt); 135 fflush(stdout); 136 while (keep_going) { 137 if (fgets(line_buf, sizeof(line_buf), stdin) == NULL) { 138 // fgets got an error. Just give up. 139 if (result != NULL) { 140 DeleteArray(result); 141 } 142 return NULL; 143 } 144 int len = StrLength(line_buf); 145 if (len > 1 && 146 line_buf[len - 2] == '\\' && 147 line_buf[len - 1] == '\n') { 148 // When we read a line that ends with a "\" we remove the escape and 149 // append the remainder. 150 line_buf[len - 2] = '\n'; 151 line_buf[len - 1] = 0; 152 len -= 1; 153 } else if ((len > 0) && (line_buf[len - 1] == '\n')) { 154 // Since we read a new line we are done reading the line. This 155 // will exit the loop after copying this buffer into the result. 156 keep_going = false; 157 } 158 if (result == NULL) { 159 // Allocate the initial result and make room for the terminating '\0' 160 result = NewArray<char>(len + 1); 161 } else { 162 // Allocate a new result with enough room for the new addition. 163 int new_len = offset + len + 1; 164 char* new_result = NewArray<char>(new_len); 165 // Copy the existing input into the new array and set the new 166 // array as the result. 167 MemCopy(new_result, result, offset * kCharSize); 168 DeleteArray(result); 169 result = new_result; 170 } 171 // Copy the newly read line into the result. 172 MemCopy(result + offset, line_buf, len * kCharSize); 173 offset += len; 174 } 175 ASSERT(result != NULL); 176 result[offset] = '\0'; 177 return result; 178 } 179 180 181 char* ReadCharsFromFile(FILE* file, 182 int* size, 183 int extra_space, 184 bool verbose, 185 const char* filename) { 186 if (file == NULL || fseek(file, 0, SEEK_END) != 0) { 187 if (verbose) { 188 OS::PrintError("Cannot read from file %s.\n", filename); 189 } 190 return NULL; 191 } 192 193 // Get the size of the file and rewind it. 194 *size = ftell(file); 195 rewind(file); 196 197 char* result = NewArray<char>(*size + extra_space); 198 for (int i = 0; i < *size && feof(file) == 0;) { 199 int read = static_cast<int>(fread(&result[i], 1, *size - i, file)); 200 if (read != (*size - i) && ferror(file) != 0) { 201 fclose(file); 202 DeleteArray(result); 203 return NULL; 204 } 205 i += read; 206 } 207 return result; 208 } 209 210 211 char* ReadCharsFromFile(const char* filename, 212 int* size, 213 int extra_space, 214 bool verbose) { 215 FILE* file = OS::FOpen(filename, "rb"); 216 char* result = ReadCharsFromFile(file, size, extra_space, verbose, filename); 217 if (file != NULL) fclose(file); 218 return result; 219 } 220 221 222 byte* ReadBytes(const char* filename, int* size, bool verbose) { 223 char* chars = ReadCharsFromFile(filename, size, 0, verbose); 224 return reinterpret_cast<byte*>(chars); 225 } 226 227 228 static Vector<const char> SetVectorContents(char* chars, 229 int size, 230 bool* exists) { 231 if (!chars) { 232 *exists = false; 233 return Vector<const char>::empty(); 234 } 235 chars[size] = '\0'; 236 *exists = true; 237 return Vector<const char>(chars, size); 238 } 239 240 241 Vector<const char> ReadFile(const char* filename, 242 bool* exists, 243 bool verbose) { 244 int size; 245 char* result = ReadCharsFromFile(filename, &size, 1, verbose); 246 return SetVectorContents(result, size, exists); 247 } 248 249 250 Vector<const char> ReadFile(FILE* file, 251 bool* exists, 252 bool verbose) { 253 int size; 254 char* result = ReadCharsFromFile(file, &size, 1, verbose, ""); 255 return SetVectorContents(result, size, exists); 256 } 257 258 259 int WriteCharsToFile(const char* str, int size, FILE* f) { 260 int total = 0; 261 while (total < size) { 262 int write = static_cast<int>(fwrite(str, 1, size - total, f)); 263 if (write == 0) { 264 return total; 265 } 266 total += write; 267 str += write; 268 } 269 return total; 270 } 271 272 273 int AppendChars(const char* filename, 274 const char* str, 275 int size, 276 bool verbose) { 277 FILE* f = OS::FOpen(filename, "ab"); 278 if (f == NULL) { 279 if (verbose) { 280 OS::PrintError("Cannot open file %s for writing.\n", filename); 281 } 282 return 0; 283 } 284 int written = WriteCharsToFile(str, size, f); 285 fclose(f); 286 return written; 287 } 288 289 290 int WriteChars(const char* filename, 291 const char* str, 292 int size, 293 bool verbose) { 294 FILE* f = OS::FOpen(filename, "wb"); 295 if (f == NULL) { 296 if (verbose) { 297 OS::PrintError("Cannot open file %s for writing.\n", filename); 298 } 299 return 0; 300 } 301 int written = WriteCharsToFile(str, size, f); 302 fclose(f); 303 return written; 304 } 305 306 307 int WriteBytes(const char* filename, 308 const byte* bytes, 309 int size, 310 bool verbose) { 311 const char* str = reinterpret_cast<const char*>(bytes); 312 return WriteChars(filename, str, size, verbose); 313 } 314 315 316 317 void StringBuilder::AddFormatted(const char* format, ...) { 318 va_list arguments; 319 va_start(arguments, format); 320 AddFormattedList(format, arguments); 321 va_end(arguments); 322 } 323 324 325 void StringBuilder::AddFormattedList(const char* format, va_list list) { 326 ASSERT(!is_finalized() && position_ <= buffer_.length()); 327 int n = VSNPrintF(buffer_ + position_, format, list); 328 if (n < 0 || n >= (buffer_.length() - position_)) { 329 position_ = buffer_.length(); 330 } else { 331 position_ += n; 332 } 333 } 334 335 336 #if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87 337 static void MemMoveWrapper(void* dest, const void* src, size_t size) { 338 memmove(dest, src, size); 339 } 340 341 342 // Initialize to library version so we can call this at any time during startup. 343 static MemMoveFunction memmove_function = &MemMoveWrapper; 344 345 // Defined in codegen-ia32.cc. 346 MemMoveFunction CreateMemMoveFunction(); 347 348 // Copy memory area to disjoint memory area. 349 void MemMove(void* dest, const void* src, size_t size) { 350 if (size == 0) return; 351 // Note: here we rely on dependent reads being ordered. This is true 352 // on all architectures we currently support. 353 (*memmove_function)(dest, src, size); 354 } 355 356 #elif V8_OS_POSIX && V8_HOST_ARCH_ARM 357 void MemCopyUint16Uint8Wrapper(uint16_t* dest, const uint8_t* src, 358 size_t chars) { 359 uint16_t* limit = dest + chars; 360 while (dest < limit) { 361 *dest++ = static_cast<uint16_t>(*src++); 362 } 363 } 364 365 366 MemCopyUint8Function memcopy_uint8_function = &MemCopyUint8Wrapper; 367 MemCopyUint16Uint8Function memcopy_uint16_uint8_function = 368 &MemCopyUint16Uint8Wrapper; 369 // Defined in codegen-arm.cc. 370 MemCopyUint8Function CreateMemCopyUint8Function(MemCopyUint8Function stub); 371 MemCopyUint16Uint8Function CreateMemCopyUint16Uint8Function( 372 MemCopyUint16Uint8Function stub); 373 374 #elif V8_OS_POSIX && V8_HOST_ARCH_MIPS 375 MemCopyUint8Function memcopy_uint8_function = &MemCopyUint8Wrapper; 376 // Defined in codegen-mips.cc. 377 MemCopyUint8Function CreateMemCopyUint8Function(MemCopyUint8Function stub); 378 #endif 379 380 381 void init_memcopy_functions() { 382 #if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87 383 MemMoveFunction generated_memmove = CreateMemMoveFunction(); 384 if (generated_memmove != NULL) { 385 memmove_function = generated_memmove; 386 } 387 #elif V8_OS_POSIX && V8_HOST_ARCH_ARM 388 memcopy_uint8_function = CreateMemCopyUint8Function(&MemCopyUint8Wrapper); 389 memcopy_uint16_uint8_function = 390 CreateMemCopyUint16Uint8Function(&MemCopyUint16Uint8Wrapper); 391 #elif V8_OS_POSIX && V8_HOST_ARCH_MIPS 392 memcopy_uint8_function = CreateMemCopyUint8Function(&MemCopyUint8Wrapper); 393 #endif 394 } 395 396 397 } } // namespace v8::internal 398