• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2006-2008 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 
PrintF(const char * format,...)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 
PrintF(FILE * out,const char * format,...)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 
Flush(FILE * out)56 void Flush(FILE* out) {
57   fflush(out);
58 }
59 
60 
ReadLine(const char * prompt)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 
ReadCharsFromFile(const char * filename,int * size,int extra_space,bool verbose)113 char* ReadCharsFromFile(const char* filename,
114                         int* size,
115                         int extra_space,
116                         bool verbose) {
117   FILE* file = OS::FOpen(filename, "rb");
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;) {
131     int read = static_cast<int>(fread(&result[i], 1, *size - i, file));
132     if (read <= 0) {
133       fclose(file);
134       DeleteArray(result);
135       return NULL;
136     }
137     i += read;
138   }
139   fclose(file);
140   return result;
141 }
142 
143 
ReadBytes(const char * filename,int * size,bool verbose)144 byte* ReadBytes(const char* filename, int* size, bool verbose) {
145   char* chars = ReadCharsFromFile(filename, size, 0, verbose);
146   return reinterpret_cast<byte*>(chars);
147 }
148 
149 
ReadFile(const char * filename,bool * exists,bool verbose)150 Vector<const char> ReadFile(const char* filename,
151                             bool* exists,
152                             bool verbose) {
153   int size;
154   char* result = ReadCharsFromFile(filename, &size, 1, verbose);
155   if (!result) {
156     *exists = false;
157     return Vector<const char>::empty();
158   }
159   result[size] = '\0';
160   *exists = true;
161   return Vector<const char>(result, size);
162 }
163 
164 
WriteCharsToFile(const char * str,int size,FILE * f)165 int WriteCharsToFile(const char* str, int size, FILE* f) {
166   int total = 0;
167   while (total < size) {
168     int write = static_cast<int>(fwrite(str, 1, size - total, f));
169     if (write == 0) {
170       return total;
171     }
172     total += write;
173     str += write;
174   }
175   return total;
176 }
177 
178 
AppendChars(const char * filename,const char * str,int size,bool verbose)179 int AppendChars(const char* filename,
180                 const char* str,
181                 int size,
182                 bool verbose) {
183   FILE* f = OS::FOpen(filename, "ab");
184   if (f == NULL) {
185     if (verbose) {
186       OS::PrintError("Cannot open file %s for writing.\n", filename);
187     }
188     return 0;
189   }
190   int written = WriteCharsToFile(str, size, f);
191   fclose(f);
192   return written;
193 }
194 
195 
WriteChars(const char * filename,const char * str,int size,bool verbose)196 int WriteChars(const char* filename,
197                const char* str,
198                int size,
199                bool verbose) {
200   FILE* f = OS::FOpen(filename, "wb");
201   if (f == NULL) {
202     if (verbose) {
203       OS::PrintError("Cannot open file %s for writing.\n", filename);
204     }
205     return 0;
206   }
207   int written = WriteCharsToFile(str, size, f);
208   fclose(f);
209   return written;
210 }
211 
212 
WriteBytes(const char * filename,const byte * bytes,int size,bool verbose)213 int WriteBytes(const char* filename,
214                const byte* bytes,
215                int size,
216                bool verbose) {
217   const char* str = reinterpret_cast<const char*>(bytes);
218   return WriteChars(filename, str, size, verbose);
219 }
220 
221 
StringBuilder(int size)222 StringBuilder::StringBuilder(int size) {
223   buffer_ = Vector<char>::New(size);
224   position_ = 0;
225 }
226 
227 
AddString(const char * s)228 void StringBuilder::AddString(const char* s) {
229   AddSubstring(s, StrLength(s));
230 }
231 
232 
AddSubstring(const char * s,int n)233 void StringBuilder::AddSubstring(const char* s, int n) {
234   ASSERT(!is_finalized() && position_ + n < buffer_.length());
235   ASSERT(static_cast<size_t>(n) <= strlen(s));
236   memcpy(&buffer_[position_], s, n * kCharSize);
237   position_ += n;
238 }
239 
240 
AddFormatted(const char * format,...)241 void StringBuilder::AddFormatted(const char* format, ...) {
242   va_list arguments;
243   va_start(arguments, format);
244   AddFormattedList(format, arguments);
245   va_end(arguments);
246 }
247 
248 
AddFormattedList(const char * format,va_list list)249 void StringBuilder::AddFormattedList(const char* format, va_list list) {
250   ASSERT(!is_finalized() && position_ < buffer_.length());
251   int n = OS::VSNPrintF(buffer_ + position_, format, list);
252   if (n < 0 || n >= (buffer_.length() - position_)) {
253     position_ = buffer_.length();
254   } else {
255     position_ += n;
256   }
257 }
258 
259 
AddPadding(char c,int count)260 void StringBuilder::AddPadding(char c, int count) {
261   for (int i = 0; i < count; i++) {
262     AddCharacter(c);
263   }
264 }
265 
266 
Finalize()267 char* StringBuilder::Finalize() {
268   ASSERT(!is_finalized() && position_ < buffer_.length());
269   buffer_[position_] = '\0';
270   // Make sure nobody managed to add a 0-character to the
271   // buffer while building the string.
272   ASSERT(strlen(buffer_.start()) == static_cast<size_t>(position_));
273   position_ = -1;
274   ASSERT(is_finalized());
275   return buffer_.start();
276 }
277 
278 
MemoryMappedExternalResource(const char * filename)279 MemoryMappedExternalResource::MemoryMappedExternalResource(const char* filename)
280     : filename_(NULL),
281       data_(NULL),
282       length_(0),
283       remove_file_on_cleanup_(false) {
284   Init(filename);
285 }
286 
287 
288 MemoryMappedExternalResource::
MemoryMappedExternalResource(const char * filename,bool remove_file_on_cleanup)289     MemoryMappedExternalResource(const char* filename,
290                                  bool remove_file_on_cleanup)
291     : filename_(NULL),
292       data_(NULL),
293       length_(0),
294       remove_file_on_cleanup_(remove_file_on_cleanup) {
295   Init(filename);
296 }
297 
298 
~MemoryMappedExternalResource()299 MemoryMappedExternalResource::~MemoryMappedExternalResource() {
300   // Release the resources if we had successfully acquired them:
301   if (file_ != NULL) {
302     delete file_;
303     if (remove_file_on_cleanup_) {
304       OS::Remove(filename_);
305     }
306     DeleteArray<char>(filename_);
307   }
308 }
309 
310 
Init(const char * filename)311 void MemoryMappedExternalResource::Init(const char* filename) {
312   file_ = OS::MemoryMappedFile::open(filename);
313   if (file_ != NULL) {
314     filename_ = StrDup(filename);
315     data_ = reinterpret_cast<char*>(file_->memory());
316     length_ = file_->size();
317   }
318 }
319 
320 
EnsureIsAscii(bool abort_if_failed) const321 bool MemoryMappedExternalResource::EnsureIsAscii(bool abort_if_failed) const {
322   bool is_ascii = true;
323 
324   int line_no = 1;
325   const char* start_of_line = data_;
326   const char* end = data_ + length_;
327   for (const char* p = data_; p < end; p++) {
328     char c = *p;
329     if ((c & 0x80) != 0) {
330       // Non-ascii detected:
331       is_ascii = false;
332 
333       // Report the error and abort if appropriate:
334       if (abort_if_failed) {
335         int char_no = static_cast<int>(p - start_of_line) - 1;
336 
337         ASSERT(filename_ != NULL);
338         PrintF("\n\n\n"
339                "Abort: Non-Ascii character 0x%.2x in file %s line %d char %d",
340                c, filename_, line_no, char_no);
341 
342         // Allow for some context up to kNumberOfLeadingContextChars chars
343         // before the offending non-ascii char to help the user see where
344         // the offending char is.
345         const int kNumberOfLeadingContextChars = 10;
346         const char* err_context = p - kNumberOfLeadingContextChars;
347         if (err_context < data_) {
348           err_context = data_;
349         }
350         // Compute the length of the error context and print it.
351         int err_context_length = static_cast<int>(p - err_context);
352         if (err_context_length != 0) {
353           PrintF(" after \"%.*s\"", err_context_length, err_context);
354         }
355         PrintF(".\n\n\n");
356         OS::Abort();
357       }
358 
359       break;  // Non-ascii detected.  No need to continue scanning.
360     }
361     if (c == '\n') {
362       start_of_line = p;
363       line_no++;
364     }
365   }
366 
367   return is_ascii;
368 }
369 
370 
371 } }  // namespace v8::internal
372