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 40 // Implementation is from "Hacker's Delight" by Henry S. Warren, Jr., 41 // figure 3-3, page 48, where the function is called clp2. 42 uint32_t RoundUpToPowerOf2(uint32_t x) { 43 ASSERT(x <= 0x80000000u); 44 x = x - 1; 45 x = x | (x >> 1); 46 x = x | (x >> 2); 47 x = x | (x >> 4); 48 x = x | (x >> 8); 49 x = x | (x >> 16); 50 return x + 1; 51 } 52 53 54 // Thomas Wang, Integer Hash Functions. 55 // http://www.concentric.net/~Ttwang/tech/inthash.htm 56 uint32_t ComputeIntegerHash(uint32_t key) { 57 uint32_t hash = key; 58 hash = ~hash + (hash << 15); // hash = (hash << 15) - hash - 1; 59 hash = hash ^ (hash >> 12); 60 hash = hash + (hash << 2); 61 hash = hash ^ (hash >> 4); 62 hash = hash * 2057; // hash = (hash + (hash << 3)) + (hash << 11); 63 hash = hash ^ (hash >> 16); 64 return hash; 65 } 66 67 68 void PrintF(const char* format, ...) { 69 va_list arguments; 70 va_start(arguments, format); 71 OS::VPrint(format, arguments); 72 va_end(arguments); 73 } 74 75 76 void Flush() { 77 fflush(stdout); 78 } 79 80 81 char* ReadLine(const char* prompt) { 82 char* result = NULL; 83 char line_buf[256]; 84 int offset = 0; 85 bool keep_going = true; 86 fprintf(stdout, "%s", prompt); 87 fflush(stdout); 88 while (keep_going) { 89 if (fgets(line_buf, sizeof(line_buf), stdin) == NULL) { 90 // fgets got an error. Just give up. 91 if (result != NULL) { 92 DeleteArray(result); 93 } 94 return NULL; 95 } 96 int len = StrLength(line_buf); 97 if (len > 1 && 98 line_buf[len - 2] == '\\' && 99 line_buf[len - 1] == '\n') { 100 // When we read a line that ends with a "\" we remove the escape and 101 // append the remainder. 102 line_buf[len - 2] = '\n'; 103 line_buf[len - 1] = 0; 104 len -= 1; 105 } else if ((len > 0) && (line_buf[len - 1] == '\n')) { 106 // Since we read a new line we are done reading the line. This 107 // will exit the loop after copying this buffer into the result. 108 keep_going = false; 109 } 110 if (result == NULL) { 111 // Allocate the initial result and make room for the terminating '\0' 112 result = NewArray<char>(len + 1); 113 } else { 114 // Allocate a new result with enough room for the new addition. 115 int new_len = offset + len + 1; 116 char* new_result = NewArray<char>(new_len); 117 // Copy the existing input into the new array and set the new 118 // array as the result. 119 memcpy(new_result, result, offset * kCharSize); 120 DeleteArray(result); 121 result = new_result; 122 } 123 // Copy the newly read line into the result. 124 memcpy(result + offset, line_buf, len * kCharSize); 125 offset += len; 126 } 127 ASSERT(result != NULL); 128 result[offset] = '\0'; 129 return result; 130 } 131 132 133 char* ReadCharsFromFile(const char* filename, 134 int* size, 135 int extra_space, 136 bool verbose) { 137 FILE* file = OS::FOpen(filename, "rb"); 138 if (file == NULL || fseek(file, 0, SEEK_END) != 0) { 139 if (verbose) { 140 OS::PrintError("Cannot read from file %s.\n", filename); 141 } 142 return NULL; 143 } 144 145 // Get the size of the file and rewind it. 146 *size = ftell(file); 147 rewind(file); 148 149 char* result = NewArray<char>(*size + extra_space); 150 for (int i = 0; i < *size;) { 151 int read = static_cast<int>(fread(&result[i], 1, *size - i, file)); 152 if (read <= 0) { 153 fclose(file); 154 DeleteArray(result); 155 return NULL; 156 } 157 i += read; 158 } 159 fclose(file); 160 return result; 161 } 162 163 164 byte* ReadBytes(const char* filename, int* size, bool verbose) { 165 char* chars = ReadCharsFromFile(filename, size, 0, verbose); 166 return reinterpret_cast<byte*>(chars); 167 } 168 169 170 Vector<const char> ReadFile(const char* filename, 171 bool* exists, 172 bool verbose) { 173 int size; 174 char* result = ReadCharsFromFile(filename, &size, 1, verbose); 175 if (!result) { 176 *exists = false; 177 return Vector<const char>::empty(); 178 } 179 result[size] = '\0'; 180 *exists = true; 181 return Vector<const char>(result, size); 182 } 183 184 185 int WriteCharsToFile(const char* str, int size, FILE* f) { 186 int total = 0; 187 while (total < size) { 188 int write = static_cast<int>(fwrite(str, 1, size - total, f)); 189 if (write == 0) { 190 return total; 191 } 192 total += write; 193 str += write; 194 } 195 return total; 196 } 197 198 199 int WriteChars(const char* filename, 200 const char* str, 201 int size, 202 bool verbose) { 203 FILE* f = OS::FOpen(filename, "wb"); 204 if (f == NULL) { 205 if (verbose) { 206 OS::PrintError("Cannot open file %s for writing.\n", filename); 207 } 208 return 0; 209 } 210 int written = WriteCharsToFile(str, size, f); 211 fclose(f); 212 return written; 213 } 214 215 216 int WriteBytes(const char* filename, 217 const byte* bytes, 218 int size, 219 bool verbose) { 220 const char* str = reinterpret_cast<const char*>(bytes); 221 return WriteChars(filename, str, size, verbose); 222 } 223 224 225 StringBuilder::StringBuilder(int size) { 226 buffer_ = Vector<char>::New(size); 227 position_ = 0; 228 } 229 230 231 void StringBuilder::AddString(const char* s) { 232 AddSubstring(s, StrLength(s)); 233 } 234 235 236 void StringBuilder::AddSubstring(const char* s, int n) { 237 ASSERT(!is_finalized() && position_ + n < buffer_.length()); 238 ASSERT(static_cast<size_t>(n) <= strlen(s)); 239 memcpy(&buffer_[position_], s, n * kCharSize); 240 position_ += n; 241 } 242 243 244 void StringBuilder::AddFormatted(const char* format, ...) { 245 ASSERT(!is_finalized() && position_ < buffer_.length()); 246 va_list args; 247 va_start(args, format); 248 int n = OS::VSNPrintF(buffer_ + position_, format, args); 249 va_end(args); 250 if (n < 0 || n >= (buffer_.length() - position_)) { 251 position_ = buffer_.length(); 252 } else { 253 position_ += n; 254 } 255 } 256 257 258 void StringBuilder::AddPadding(char c, int count) { 259 for (int i = 0; i < count; i++) { 260 AddCharacter(c); 261 } 262 } 263 264 265 char* StringBuilder::Finalize() { 266 ASSERT(!is_finalized() && position_ < buffer_.length()); 267 buffer_[position_] = '\0'; 268 // Make sure nobody managed to add a 0-character to the 269 // buffer while building the string. 270 ASSERT(strlen(buffer_.start()) == static_cast<size_t>(position_)); 271 position_ = -1; 272 ASSERT(is_finalized()); 273 return buffer_.start(); 274 } 275 276 277 int TenToThe(int exponent) { 278 ASSERT(exponent <= 9); 279 ASSERT(exponent >= 1); 280 int answer = 10; 281 for (int i = 1; i < exponent; i++) answer *= 10; 282 return answer; 283 } 284 285 } } // namespace v8::internal 286