Home | History | Annotate | Download | only in src
      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