Home | History | Annotate | Download | only in src
      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 Flush(FILE* out) {
     57   fflush(out);
     58 }
     59 
     60 
     61 char* ReadLine(const char* prompt) {
     62   char* result = NULL;
     63   char line_buf[256];
     64   int offset = 0;
     65   bool keep_going = true;
     66   fprintf(stdout, "%s", prompt);
     67   fflush(stdout);
     68   while (keep_going) {
     69     if (fgets(line_buf, sizeof(line_buf), stdin) == NULL) {
     70       // fgets got an error. Just give up.
     71       if (result != NULL) {
     72         DeleteArray(result);
     73       }
     74       return NULL;
     75     }
     76     int len = StrLength(line_buf);
     77     if (len > 1 &&
     78         line_buf[len - 2] == '\\' &&
     79         line_buf[len - 1] == '\n') {
     80       // When we read a line that ends with a "\" we remove the escape and
     81       // append the remainder.
     82       line_buf[len - 2] = '\n';
     83       line_buf[len - 1] = 0;
     84       len -= 1;
     85     } else if ((len > 0) && (line_buf[len - 1] == '\n')) {
     86       // Since we read a new line we are done reading the line. This
     87       // will exit the loop after copying this buffer into the result.
     88       keep_going = false;
     89     }
     90     if (result == NULL) {
     91       // Allocate the initial result and make room for the terminating '\0'
     92       result = NewArray<char>(len + 1);
     93     } else {
     94       // Allocate a new result with enough room for the new addition.
     95       int new_len = offset + len + 1;
     96       char* new_result = NewArray<char>(new_len);
     97       // Copy the existing input into the new array and set the new
     98       // array as the result.
     99       memcpy(new_result, result, offset * kCharSize);
    100       DeleteArray(result);
    101       result = new_result;
    102     }
    103     // Copy the newly read line into the result.
    104     memcpy(result + offset, line_buf, len * kCharSize);
    105     offset += len;
    106   }
    107   ASSERT(result != NULL);
    108   result[offset] = '\0';
    109   return result;
    110 }
    111 
    112 
    113 char* ReadCharsFromFile(FILE* file,
    114                         int* size,
    115                         int extra_space,
    116                         bool verbose,
    117                         const char* filename) {
    118   if (file == NULL || fseek(file, 0, SEEK_END) != 0) {
    119     if (verbose) {
    120       OS::PrintError("Cannot read from file %s.\n", filename);
    121     }
    122     return NULL;
    123   }
    124 
    125   // Get the size of the file and rewind it.
    126   *size = ftell(file);
    127   rewind(file);
    128 
    129   char* result = NewArray<char>(*size + extra_space);
    130   for (int i = 0; i < *size && feof(file) == 0;) {
    131     int read = static_cast<int>(fread(&result[i], 1, *size - i, file));
    132     if (read != (*size - i) && ferror(file) != 0) {
    133       fclose(file);
    134       DeleteArray(result);
    135       return NULL;
    136     }
    137     i += read;
    138   }
    139   return result;
    140 }
    141 
    142 
    143 char* ReadCharsFromFile(const char* filename,
    144                         int* size,
    145                         int extra_space,
    146                         bool verbose) {
    147   FILE* file = OS::FOpen(filename, "rb");
    148   char* result = ReadCharsFromFile(file, size, extra_space, verbose, filename);
    149   if (file != NULL) fclose(file);
    150   return result;
    151 }
    152 
    153 
    154 byte* ReadBytes(const char* filename, int* size, bool verbose) {
    155   char* chars = ReadCharsFromFile(filename, size, 0, verbose);
    156   return reinterpret_cast<byte*>(chars);
    157 }
    158 
    159 
    160 static Vector<const char> SetVectorContents(char* chars,
    161                                             int size,
    162                                             bool* exists) {
    163   if (!chars) {
    164     *exists = false;
    165     return Vector<const char>::empty();
    166   }
    167   chars[size] = '\0';
    168   *exists = true;
    169   return Vector<const char>(chars, size);
    170 }
    171 
    172 
    173 Vector<const char> ReadFile(const char* filename,
    174                             bool* exists,
    175                             bool verbose) {
    176   int size;
    177   char* result = ReadCharsFromFile(filename, &size, 1, verbose);
    178   return SetVectorContents(result, size, exists);
    179 }
    180 
    181 
    182 Vector<const char> ReadFile(FILE* file,
    183                             bool* exists,
    184                             bool verbose) {
    185   int size;
    186   char* result = ReadCharsFromFile(file, &size, 1, verbose, "");
    187   return SetVectorContents(result, size, exists);
    188 }
    189 
    190 
    191 int WriteCharsToFile(const char* str, int size, FILE* f) {
    192   int total = 0;
    193   while (total < size) {
    194     int write = static_cast<int>(fwrite(str, 1, size - total, f));
    195     if (write == 0) {
    196       return total;
    197     }
    198     total += write;
    199     str += write;
    200   }
    201   return total;
    202 }
    203 
    204 
    205 int AppendChars(const char* filename,
    206                 const char* str,
    207                 int size,
    208                 bool verbose) {
    209   FILE* f = OS::FOpen(filename, "ab");
    210   if (f == NULL) {
    211     if (verbose) {
    212       OS::PrintError("Cannot open file %s for writing.\n", filename);
    213     }
    214     return 0;
    215   }
    216   int written = WriteCharsToFile(str, size, f);
    217   fclose(f);
    218   return written;
    219 }
    220 
    221 
    222 int WriteChars(const char* filename,
    223                const char* str,
    224                int size,
    225                bool verbose) {
    226   FILE* f = OS::FOpen(filename, "wb");
    227   if (f == NULL) {
    228     if (verbose) {
    229       OS::PrintError("Cannot open file %s for writing.\n", filename);
    230     }
    231     return 0;
    232   }
    233   int written = WriteCharsToFile(str, size, f);
    234   fclose(f);
    235   return written;
    236 }
    237 
    238 
    239 int WriteBytes(const char* filename,
    240                const byte* bytes,
    241                int size,
    242                bool verbose) {
    243   const char* str = reinterpret_cast<const char*>(bytes);
    244   return WriteChars(filename, str, size, verbose);
    245 }
    246 
    247 
    248 
    249 void StringBuilder::AddFormatted(const char* format, ...) {
    250   va_list arguments;
    251   va_start(arguments, format);
    252   AddFormattedList(format, arguments);
    253   va_end(arguments);
    254 }
    255 
    256 
    257 void StringBuilder::AddFormattedList(const char* format, va_list list) {
    258   ASSERT(!is_finalized() && position_ < buffer_.length());
    259   int n = OS::VSNPrintF(buffer_ + position_, format, list);
    260   if (n < 0 || n >= (buffer_.length() - position_)) {
    261     position_ = buffer_.length();
    262   } else {
    263     position_ += n;
    264   }
    265 }
    266 
    267 
    268 MemoryMappedExternalResource::MemoryMappedExternalResource(const char* filename)
    269     : filename_(NULL),
    270       data_(NULL),
    271       length_(0),
    272       remove_file_on_cleanup_(false) {
    273   Init(filename);
    274 }
    275 
    276 
    277 MemoryMappedExternalResource::
    278     MemoryMappedExternalResource(const char* filename,
    279                                  bool remove_file_on_cleanup)
    280     : filename_(NULL),
    281       data_(NULL),
    282       length_(0),
    283       remove_file_on_cleanup_(remove_file_on_cleanup) {
    284   Init(filename);
    285 }
    286 
    287 
    288 MemoryMappedExternalResource::~MemoryMappedExternalResource() {
    289   // Release the resources if we had successfully acquired them:
    290   if (file_ != NULL) {
    291     delete file_;
    292     if (remove_file_on_cleanup_) {
    293       OS::Remove(filename_);
    294     }
    295     DeleteArray<char>(filename_);
    296   }
    297 }
    298 
    299 
    300 void MemoryMappedExternalResource::Init(const char* filename) {
    301   file_ = OS::MemoryMappedFile::open(filename);
    302   if (file_ != NULL) {
    303     filename_ = StrDup(filename);
    304     data_ = reinterpret_cast<char*>(file_->memory());
    305     length_ = file_->size();
    306   }
    307 }
    308 
    309 
    310 bool MemoryMappedExternalResource::EnsureIsAscii(bool abort_if_failed) const {
    311   bool is_ascii = true;
    312 
    313   int line_no = 1;
    314   const char* start_of_line = data_;
    315   const char* end = data_ + length_;
    316   for (const char* p = data_; p < end; p++) {
    317     char c = *p;
    318     if ((c & 0x80) != 0) {
    319       // Non-ASCII detected:
    320       is_ascii = false;
    321 
    322       // Report the error and abort if appropriate:
    323       if (abort_if_failed) {
    324         int char_no = static_cast<int>(p - start_of_line) - 1;
    325 
    326         ASSERT(filename_ != NULL);
    327         PrintF("\n\n\n"
    328                "Abort: Non-Ascii character 0x%.2x in file %s line %d char %d",
    329                c, filename_, line_no, char_no);
    330 
    331         // Allow for some context up to kNumberOfLeadingContextChars chars
    332         // before the offending non-ASCII char to help the user see where
    333         // the offending char is.
    334         const int kNumberOfLeadingContextChars = 10;
    335         const char* err_context = p - kNumberOfLeadingContextChars;
    336         if (err_context < data_) {
    337           err_context = data_;
    338         }
    339         // Compute the length of the error context and print it.
    340         int err_context_length = static_cast<int>(p - err_context);
    341         if (err_context_length != 0) {
    342           PrintF(" after \"%.*s\"", err_context_length, err_context);
    343         }
    344         PrintF(".\n\n\n");
    345         OS::Abort();
    346       }
    347 
    348       break;  // Non-ASCII detected.  No need to continue scanning.
    349     }
    350     if (c == '\n') {
    351       start_of_line = p;
    352       line_no++;
    353     }
    354   }
    355 
    356   return is_ascii;
    357 }
    358 
    359 
    360 } }  // namespace v8::internal
    361