• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
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(FILE * file,int * size,int extra_space,bool verbose,const char * filename)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 
ReadCharsFromFile(const char * filename,int * size,int extra_space,bool verbose)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 
ReadBytes(const char * filename,int * size,bool verbose)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 
SetVectorContents(char * chars,int size,bool * exists)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 
ReadFile(const char * filename,bool * exists,bool verbose)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 
ReadFile(FILE * file,bool * exists,bool verbose)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 
WriteCharsToFile(const char * str,int size,FILE * f)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 
AppendChars(const char * filename,const char * str,int size,bool verbose)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 
WriteChars(const char * filename,const char * str,int size,bool verbose)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 
WriteBytes(const char * filename,const byte * bytes,int size,bool verbose)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 
AddFormatted(const char * format,...)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 
AddFormattedList(const char * format,va_list list)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 
MemoryMappedExternalResource(const char * filename)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::
MemoryMappedExternalResource(const char * filename,bool remove_file_on_cleanup)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 
~MemoryMappedExternalResource()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 
Init(const char * filename)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 
EnsureIsAscii(bool abort_if_failed) const310 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