OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 10 matching lines...) Expand all Loading... |
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
28 #include <stdlib.h> | 28 #include <stdlib.h> |
29 #include <stdarg.h> | 29 #include <stdarg.h> |
30 #include <stdio.h> | 30 #include <stdio.h> |
| 31 #include <string.h> |
31 | 32 |
32 #include "../include/v8stdint.h" | 33 #include "../include/v8stdint.h" |
33 #include "../include/v8-preparser.h" | 34 #include "../include/v8-preparser.h" |
34 | 35 |
| 36 #include "../src/preparse-data-format.h" |
| 37 |
| 38 namespace i = v8::internal; |
| 39 |
35 // This file is only used for testing the stand-alone preparser | 40 // This file is only used for testing the stand-alone preparser |
36 // library. | 41 // library. |
37 // The first (and only) argument must be the path of a JavaScript file. | 42 // The first argument must be the path of a JavaScript source file. |
38 // This file is preparsed and the resulting preparser data is written | 43 // Optionally this can be followed by the word "throws" (case sensitive), |
39 // to stdout. Diagnostic output is output on stderr. | 44 // which signals that the parsing is expected to throw - the default is |
40 // The file must contain only ASCII characters (UTF-8 isn't supported). | 45 // to expect the parsing to not throw. |
| 46 // The command line can further be followed by a message text (the |
| 47 // *type* of the exception to throw), and even more optionally, the |
| 48 // start and end position reported with the exception. |
| 49 // |
| 50 // This source file is preparsed and tested against the expectations, and if |
| 51 // successful, the resulting preparser data is written to stdout. |
| 52 // Diagnostic output is output on stderr. |
| 53 // The source file must contain only ASCII characters (UTF-8 isn't supported). |
41 // The file is read into memory, so it should have a reasonable size. | 54 // The file is read into memory, so it should have a reasonable size. |
42 | 55 |
43 | 56 |
44 // Adapts an ASCII string to the UnicodeInputStream interface. | 57 // Adapts an ASCII string to the UnicodeInputStream interface. |
45 class AsciiInputStream : public v8::UnicodeInputStream { | 58 class AsciiInputStream : public v8::UnicodeInputStream { |
46 public: | 59 public: |
47 AsciiInputStream(uint8_t* buffer, size_t length) | 60 AsciiInputStream(uint8_t* buffer, size_t length) |
48 : buffer_(buffer), | 61 : buffer_(buffer), |
49 end_offset_(static_cast<int>(length)), | 62 end_offset_(static_cast<int>(length)), |
50 offset_(0) { } | 63 offset_(0) { } |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
90 return (actually_read == length); | 103 return (actually_read == length); |
91 } | 104 } |
92 | 105 |
93 | 106 |
94 bool WriteBuffer(FILE* dest, const void* buffer, size_t length) { | 107 bool WriteBuffer(FILE* dest, const void* buffer, size_t length) { |
95 size_t actually_written = fwrite(buffer, 1, length, dest); | 108 size_t actually_written = fwrite(buffer, 1, length, dest); |
96 return (actually_written == length); | 109 return (actually_written == length); |
97 } | 110 } |
98 | 111 |
99 | 112 |
| 113 class PreparseDataInterpreter { |
| 114 public: |
| 115 PreparseDataInterpreter(const uint8_t* data, int length) |
| 116 : data_(data), length_(length), message_(NULL) { } |
| 117 |
| 118 ~PreparseDataInterpreter() { |
| 119 if (message_ != NULL) delete[] message_; |
| 120 } |
| 121 |
| 122 bool valid() { |
| 123 int header_length = |
| 124 i::PreparseDataConstants::kHeaderSize * sizeof(int); // NOLINT |
| 125 return length_ >= header_length; |
| 126 } |
| 127 |
| 128 bool throws() { |
| 129 return valid() && |
| 130 word(i::PreparseDataConstants::kHasErrorOffset) != 0; |
| 131 } |
| 132 |
| 133 const char* message() { |
| 134 if (message_ != NULL) return message_; |
| 135 if (!throws()) return NULL; |
| 136 int text_pos = i::PreparseDataConstants::kHeaderSize + |
| 137 i::PreparseDataConstants::kMessageTextPos; |
| 138 int length = word(text_pos); |
| 139 char* buffer = new char[length + 1]; |
| 140 for (int i = 1; i <= length; i++) { |
| 141 int character = word(text_pos + i); |
| 142 buffer[i - 1] = character; |
| 143 } |
| 144 buffer[length] = '\0'; |
| 145 message_ = buffer; |
| 146 return buffer; |
| 147 } |
| 148 |
| 149 int beg_pos() { |
| 150 if (!throws()) return -1; |
| 151 return word(i::PreparseDataConstants::kHeaderSize + |
| 152 i::PreparseDataConstants::kMessageStartPos); |
| 153 } |
| 154 |
| 155 int end_pos() { |
| 156 if (!throws()) return -1; |
| 157 return word(i::PreparseDataConstants::kHeaderSize + |
| 158 i::PreparseDataConstants::kMessageEndPos); |
| 159 } |
| 160 |
| 161 private: |
| 162 int word(int offset) { |
| 163 const int* word_data = reinterpret_cast<const int*>(data_); |
| 164 if (word_data + offset < reinterpret_cast<const int*>(data_ + length_)) { |
| 165 return word_data[offset]; |
| 166 } |
| 167 return -1; |
| 168 } |
| 169 |
| 170 const uint8_t* const data_; |
| 171 const int length_; |
| 172 const char* message_; |
| 173 }; |
| 174 |
| 175 |
100 template <typename T> | 176 template <typename T> |
101 class ScopedPointer { | 177 class ScopedPointer { |
102 public: | 178 public: |
103 explicit ScopedPointer(T* pointer) : pointer_(pointer) {} | 179 explicit ScopedPointer(T* pointer) : pointer_(pointer) {} |
104 ~ScopedPointer() { delete[] pointer_; } | 180 ~ScopedPointer() { delete[] pointer_; } |
105 T& operator[](int index) { return pointer_[index]; } | 181 T& operator[](int index) { return pointer_[index]; } |
106 T* operator*() { return pointer_ ;} | 182 T* operator*() { return pointer_ ;} |
107 private: | 183 private: |
108 T* pointer_; | 184 T* pointer_; |
109 }; | 185 }; |
110 | 186 |
111 | 187 |
| 188 |
| 189 void fail(v8::PreParserData* data, const char* message, ...) { |
| 190 va_list args; |
| 191 va_start(args, message); |
| 192 vfprintf(stderr, message, args); |
| 193 va_end(args); |
| 194 fflush(stderr); |
| 195 // Print preparser data to stdout. |
| 196 uint32_t size = data->size(); |
| 197 fprintf(stderr, "LOG: data size: %u\n", size); |
| 198 if (!WriteBuffer(stdout, data->data(), size)) { |
| 199 perror("ERROR: Writing data"); |
| 200 fflush(stderr); |
| 201 } |
| 202 exit(EXIT_FAILURE); |
| 203 }; |
| 204 |
| 205 |
| 206 void CheckException(v8::PreParserData* data, |
| 207 bool throws, |
| 208 const char* message, |
| 209 int beg_pos, |
| 210 int end_pos) { |
| 211 PreparseDataInterpreter reader(data->data(), data->size()); |
| 212 if (throws) { |
| 213 if (!reader.throws()) { |
| 214 if (message == NULL) { |
| 215 fail(data, "Didn't throw as expected\n"); |
| 216 } else { |
| 217 fail(data, "Didn't throw \"%s\" as expected\n", message); |
| 218 } |
| 219 } |
| 220 if (message != NULL) { |
| 221 const char* actual_message = reader.message(); |
| 222 if (strcmp(message, actual_message)) { |
| 223 fail(data, "Wrong error message. Expected <%s>, found <%s>\n", |
| 224 message, actual_message); |
| 225 } |
| 226 } |
| 227 if (beg_pos >= 0) { |
| 228 if (beg_pos != reader.beg_pos()) { |
| 229 fail(data, "Wrong error start position: Expected %i, found %i\n", |
| 230 beg_pos, reader.beg_pos()); |
| 231 } |
| 232 } |
| 233 if (end_pos >= 0) { |
| 234 if (end_pos != reader.end_pos()) { |
| 235 fail(data, "Wrong error end position: Expected %i, found %i\n", |
| 236 end_pos, reader.end_pos()); |
| 237 } |
| 238 } |
| 239 } else if (reader.throws()) { |
| 240 const char* message = reader.message(); |
| 241 fail(data, "Throws unexpectedly with message: %s\n", |
| 242 message); |
| 243 } |
| 244 } |
| 245 |
112 int main(int argc, char* argv[]) { | 246 int main(int argc, char* argv[]) { |
113 // Check for filename argument. | 247 // Check for filename argument. |
114 if (argc < 2) { | 248 if (argc < 2) { |
115 fprintf(stderr, "ERROR: No filename on command line.\n"); | 249 fail(NULL, "ERROR: No filename on command line.\n"); |
116 fflush(stderr); | |
117 return EXIT_FAILURE; | |
118 } | 250 } |
119 const char* filename = argv[1]; | 251 const char* filename = argv[1]; |
120 | 252 |
| 253 // Parse expectations. |
| 254 bool throws = false; |
| 255 const char* throws_message = NULL; |
| 256 int throws_beg_pos = -1; |
| 257 int throws_end_pos = -1; |
| 258 // Check for throws argument. |
| 259 if (argc > 2) { |
| 260 if (strncmp("throws", argv[2], 6)) { |
| 261 fail(NULL, "ERROR: Extra arguments not prefixed by \"throws\".\n"); |
| 262 } |
| 263 throws = true; |
| 264 if (argc > 3) { |
| 265 throws_message = argv[3]; |
| 266 } |
| 267 if (argc > 4) { |
| 268 throws_beg_pos = atoi(argv[4]); |
| 269 } |
| 270 if (argc > 5) { |
| 271 throws_end_pos = atoi(argv[5]); |
| 272 } |
| 273 } |
| 274 |
121 // Open JS file. | 275 // Open JS file. |
122 FILE* input = fopen(filename, "rb"); | 276 FILE* input = fopen(filename, "rb"); |
123 if (input == NULL) { | 277 if (input == NULL) { |
124 perror("ERROR: Error opening file"); | 278 perror("ERROR: Error opening file"); |
125 fflush(stderr); | 279 fflush(stderr); |
126 return EXIT_FAILURE; | 280 return EXIT_FAILURE; |
127 } | 281 } |
128 | 282 |
129 // Find length of JS file. | 283 // Find length of JS file. |
130 if (fseek(input, 0, SEEK_END) != 0) { | 284 if (fseek(input, 0, SEEK_END) != 0) { |
(...skipping 13 matching lines...) Expand all Loading... |
144 } | 298 } |
145 fclose(input); | 299 fclose(input); |
146 | 300 |
147 // Preparse input file. | 301 // Preparse input file. |
148 AsciiInputStream input_buffer(*buffer, length); | 302 AsciiInputStream input_buffer(*buffer, length); |
149 size_t kMaxStackSize = 64 * 1024 * sizeof(void*); // NOLINT | 303 size_t kMaxStackSize = 64 * 1024 * sizeof(void*); // NOLINT |
150 v8::PreParserData data = v8::Preparse(&input_buffer, kMaxStackSize); | 304 v8::PreParserData data = v8::Preparse(&input_buffer, kMaxStackSize); |
151 | 305 |
152 // Fail if stack overflow. | 306 // Fail if stack overflow. |
153 if (data.stack_overflow()) { | 307 if (data.stack_overflow()) { |
154 fprintf(stderr, "ERROR: Stack overflow\n"); | 308 fail(&data, "ERROR: Stack overflow\n"); |
155 fflush(stderr); | |
156 return EXIT_FAILURE; | |
157 } | 309 } |
158 | 310 |
159 // Print preparser data to stdout. | 311 // Check that the expected exception is thrown, if an exception is |
160 uint32_t size = data.size(); | 312 // expected. |
161 fprintf(stderr, "LOG: Success, data size: %u\n", size); | 313 CheckException(&data, throws, throws_message, |
162 fflush(stderr); | 314 throws_beg_pos, throws_end_pos); |
163 if (!WriteBuffer(stdout, data.data(), size)) { | |
164 perror("ERROR: Writing data"); | |
165 return EXIT_FAILURE; | |
166 } | |
167 | 315 |
168 return EXIT_SUCCESS; | 316 return EXIT_SUCCESS; |
169 } | 317 } |
OLD | NEW |