1 // Copyright 2010 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 <stdlib.h> 29 #include <stdarg.h> 30 #include <stdio.h> 31 32 #include "../include/v8stdint.h" 33 #include "../include/v8-preparser.h" 34 35 // This file is only used for testing the stand-alone preparser 36 // library. 37 // The first (and only) argument must be the path of a JavaScript file. 38 // This file is preparsed and the resulting preparser data is written 39 // to stdout. Diagnostic output is output on stderr. 40 // The 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. 42 43 44 // Adapts an ASCII string to the UnicodeInputStream interface. 45 class AsciiInputStream : public v8::UnicodeInputStream { 46 public: 47 AsciiInputStream(uint8_t* buffer, size_t length) 48 : buffer_(buffer), 49 end_offset_(static_cast<int>(length)), 50 offset_(0) { } 51 52 virtual ~AsciiInputStream() { } 53 54 virtual void PushBack(int32_t ch) { 55 offset_--; 56 #ifdef DEBUG 57 if (offset_ < 0 || 58 (ch != ((offset_ >= end_offset_) ? -1 : buffer_[offset_]))) { 59 fprintf(stderr, "Invalid pushback: '%c' at offset %d.", ch, offset_); 60 exit(1); 61 } 62 #endif 63 } 64 65 virtual int32_t Next() { 66 if (offset_ >= end_offset_) { 67 offset_++; // Increment anyway to allow symmetric pushbacks. 68 return -1; 69 } 70 uint8_t next_char = buffer_[offset_]; 71 #ifdef DEBUG 72 if (next_char > 0x7fu) { 73 fprintf(stderr, "Non-ASCII character in input: '%c'.", next_char); 74 exit(1); 75 } 76 #endif 77 offset_++; 78 return static_cast<int32_t>(next_char); 79 } 80 81 private: 82 const uint8_t* buffer_; 83 const int end_offset_; 84 int offset_; 85 }; 86 87 88 bool ReadBuffer(FILE* source, void* buffer, size_t length) { 89 size_t actually_read = fread(buffer, 1, length, source); 90 return (actually_read == length); 91 } 92 93 94 bool WriteBuffer(FILE* dest, const void* buffer, size_t length) { 95 size_t actually_written = fwrite(buffer, 1, length, dest); 96 return (actually_written == length); 97 } 98 99 100 template <typename T> 101 class ScopedPointer { 102 public: 103 explicit ScopedPointer(T* pointer) : pointer_(pointer) {} 104 ~ScopedPointer() { delete[] pointer_; } 105 T& operator[](int index) { return pointer_[index]; } 106 T* operator*() { return pointer_ ;} 107 private: 108 T* pointer_; 109 }; 110 111 112 int main(int argc, char* argv[]) { 113 // Check for filename argument. 114 if (argc < 2) { 115 fprintf(stderr, "ERROR: No filename on command line.\n"); 116 fflush(stderr); 117 return EXIT_FAILURE; 118 } 119 const char* filename = argv[1]; 120 121 // Open JS file. 122 FILE* input = fopen(filename, "rb"); 123 if (input == NULL) { 124 perror("ERROR: Error opening file"); 125 fflush(stderr); 126 return EXIT_FAILURE; 127 } 128 129 // Find length of JS file. 130 if (fseek(input, 0, SEEK_END) != 0) { 131 perror("ERROR: Error during seek"); 132 fflush(stderr); 133 return EXIT_FAILURE; 134 } 135 size_t length = static_cast<size_t>(ftell(input)); 136 rewind(input); 137 138 // Read JS file into memory buffer. 139 ScopedPointer<uint8_t> buffer(new uint8_t[length]); 140 if (!ReadBuffer(input, *buffer, length)) { 141 perror("ERROR: Reading file"); 142 fflush(stderr); 143 return EXIT_FAILURE; 144 } 145 fclose(input); 146 147 // Preparse input file. 148 AsciiInputStream input_buffer(*buffer, length); 149 size_t kMaxStackSize = 64 * 1024 * sizeof(void*); // NOLINT 150 v8::PreParserData data = v8::Preparse(&input_buffer, kMaxStackSize); 151 152 // Fail if stack overflow. 153 if (data.stack_overflow()) { 154 fprintf(stderr, "ERROR: Stack overflow\n"); 155 fflush(stderr); 156 return EXIT_FAILURE; 157 } 158 159 // Print preparser data to stdout. 160 uint32_t size = data.size(); 161 fprintf(stderr, "LOG: Success, data size: %u\n", size); 162 fflush(stderr); 163 if (!WriteBuffer(stdout, data.data(), size)) { 164 perror("ERROR: Writing data"); 165 return EXIT_FAILURE; 166 } 167 168 return EXIT_SUCCESS; 169 } 170