source: webkit/trunk/Source/JavaScriptCore/jsc.cpp@ 79177

Last change on this file since 79177 was 79177, checked in by [email protected], 14 years ago

https://bugs.webkit.org/show_bug.cgi?id=54839
Remove PrototypeFunction, NativeFunctionWrapper, and GlobalEvalFunction.

Reviewed by Oliver Hunt.

Historically, Native functions used to be represented by PrototypeFunctions, however
since introducing call optimizations to the JIT this has used JSFunctions for host
calls too. At the point this change was made, the interpreter continued to use
PrototypeFunctions, however since fallback from the JIT to interpreter was introduced
the interpreter has had to be able to run using host functions represented using
JSFunctions - leading to an unnecessary and redundant divergence in behaviour between
interpreter only builds, and situations where the JIT has fallen back to interpreting.

NativeFunctionWrapper only existed to select between PrototypeFunction and JSFunction
for wrappers for host functions, and as such can also be removed.

GlobalEvalFunction is a redundant wrapper that happens to be derived from
PrototypeFunction. It existed to hold a reference to the global object - but since all
functions how derive from JSObjectWithGlobalObject, this no longer requires an
additional class to provide this functionality.

Source/JavaScriptCore:

Removed symbols / references to files.

  • runtime/GlobalEvalFunction.cpp: Removed.
  • runtime/GlobalEvalFunction.h: Removed.
  • runtime/NativeFunctionWrapper.h: Removed.
  • runtime/PrototypeFunction.cpp: Removed.
  • runtime/PrototypeFunction.h: Removed.

Removed.

  • runtime/Executable.cpp:

(JSC::NativeExecutable::~NativeExecutable):

  • runtime/Executable.h:

(JSC::NativeExecutable::create):
(JSC::NativeExecutable::NativeExecutable):
(JSC::JSFunction::nativeFunction):

  • runtime/JSFunction.cpp:

(JSC::callHostFunctionAsConstructor):
(JSC::JSFunction::JSFunction):
(JSC::JSFunction::getCallData):

  • runtime/JSFunction.h:
  • runtime/JSGlobalData.cpp:

(JSC::JSGlobalData::getHostFunction):

  • runtime/JSGlobalData.h:

(JSC::JSGlobalData::getCTIStub):

Added interpreter-friendly constructors for NativeExecutables.

  • bytecompiler/BytecodeGenerator.cpp:
  • interpreter/Interpreter.cpp:
  • jit/JITStubs.cpp:
  • jsc.cpp:
  • runtime/ArrayConstructor.cpp:
  • runtime/BooleanPrototype.cpp:
  • runtime/BooleanPrototype.h:
  • runtime/CallData.h:
  • runtime/DateConstructor.cpp:
  • runtime/DateConstructor.h:
  • runtime/ErrorPrototype.cpp:
  • runtime/ErrorPrototype.h:
  • runtime/FunctionPrototype.cpp:
  • runtime/FunctionPrototype.h:
  • runtime/JSGlobalObject.cpp:
  • runtime/JSGlobalObject.h:
  • runtime/JSGlobalObjectFunctions.cpp:
  • runtime/Lookup.cpp:
  • runtime/NumberPrototype.cpp:
  • runtime/NumberPrototype.h:
  • runtime/ObjectConstructor.cpp:
  • runtime/ObjectConstructor.h:
  • runtime/ObjectPrototype.cpp:
  • runtime/ObjectPrototype.h:
  • runtime/RegExpPrototype.cpp:
  • runtime/RegExpPrototype.h:
  • runtime/SmallStrings.h:
  • runtime/StringConstructor.cpp:
  • runtime/StringConstructor.h:

Removed use of redundant classes.

Source/WebCore:

  • bindings/js/JSDOMBinding.cpp:
  • bindings/js/JSDOMWindowCustom.cpp:
  • bindings/js/JSHistoryCustom.cpp:
  • bindings/js/JSLocationCustom.cpp:

Removed use of redundant classes.

  • Property svn:eol-style set to native
File size: 18.3 KB
Line 
1/*
2 * Copyright (C) 1999-2000 Harri Porten ([email protected])
3 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
4 * Copyright (C) 2006 Bjoern Graf ([email protected])
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 */
22
23#include "config.h"
24
25#include "BytecodeGenerator.h"
26#include "Completion.h"
27#include "CurrentTime.h"
28#include "ExceptionHelpers.h"
29#include "InitializeThreading.h"
30#include "JSArray.h"
31#include "JSFunction.h"
32#include "JSLock.h"
33#include "JSString.h"
34#include "SamplingTool.h"
35#include <math.h>
36#include <stdio.h>
37#include <stdlib.h>
38#include <string.h>
39
40#if !OS(WINDOWS)
41#include <unistd.h>
42#endif
43
44#if HAVE(READLINE)
45#include <readline/history.h>
46#include <readline/readline.h>
47#endif
48
49#if HAVE(SYS_TIME_H)
50#include <sys/time.h>
51#endif
52
53#if HAVE(SIGNAL_H)
54#include <signal.h>
55#endif
56
57#if COMPILER(MSVC) && !OS(WINCE)
58#include <crtdbg.h>
59#include <mmsystem.h>
60#include <windows.h>
61#endif
62
63#if PLATFORM(QT)
64#include <QCoreApplication>
65#include <QDateTime>
66#endif
67
68using namespace JSC;
69using namespace WTF;
70
71static void cleanupGlobalData(JSGlobalData*);
72static bool fillBufferWithContentsOfFile(const UString& fileName, Vector<char>& buffer);
73
74static EncodedJSValue JSC_HOST_CALL functionPrint(ExecState*);
75static EncodedJSValue JSC_HOST_CALL functionDebug(ExecState*);
76static EncodedJSValue JSC_HOST_CALL functionGC(ExecState*);
77static EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*);
78static EncodedJSValue JSC_HOST_CALL functionRun(ExecState*);
79static EncodedJSValue JSC_HOST_CALL functionLoad(ExecState*);
80static EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState*);
81static EncodedJSValue JSC_HOST_CALL functionReadline(ExecState*);
82static NO_RETURN_WITH_VALUE EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*);
83
84#if ENABLE(SAMPLING_FLAGS)
85static EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState*);
86static EncodedJSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState*);
87#endif
88
89struct Script {
90 bool isFile;
91 char* argument;
92
93 Script(bool isFile, char *argument)
94 : isFile(isFile)
95 , argument(argument)
96 {
97 }
98};
99
100struct Options {
101 Options()
102 : interactive(false)
103 , dump(false)
104 {
105 }
106
107 bool interactive;
108 bool dump;
109 Vector<Script> scripts;
110 Vector<UString> arguments;
111};
112
113static const char interactivePrompt[] = "> ";
114static const UString interpreterName("Interpreter");
115
116class StopWatch {
117public:
118 void start();
119 void stop();
120 long getElapsedMS(); // call stop() first
121
122private:
123 double m_startTime;
124 double m_stopTime;
125};
126
127void StopWatch::start()
128{
129 m_startTime = currentTime();
130}
131
132void StopWatch::stop()
133{
134 m_stopTime = currentTime();
135}
136
137long StopWatch::getElapsedMS()
138{
139 return static_cast<long>((m_stopTime - m_startTime) * 1000);
140}
141
142class GlobalObject : public JSGlobalObject {
143public:
144 GlobalObject(const Vector<UString>& arguments);
145 virtual UString className() const { return "global"; }
146};
147COMPILE_ASSERT(!IsInteger<GlobalObject>::value, WTF_IsInteger_GlobalObject_false);
148ASSERT_CLASS_FITS_IN_CELL(GlobalObject);
149
150GlobalObject::GlobalObject(const Vector<UString>& arguments)
151 : JSGlobalObject()
152{
153 putDirectFunction(globalExec(), new (globalExec()) JSFunction(globalExec(), this, functionStructure(), 1, Identifier(globalExec(), "debug"), functionDebug));
154 putDirectFunction(globalExec(), new (globalExec()) JSFunction(globalExec(), this, functionStructure(), 1, Identifier(globalExec(), "print"), functionPrint));
155 putDirectFunction(globalExec(), new (globalExec()) JSFunction(globalExec(), this, functionStructure(), 0, Identifier(globalExec(), "quit"), functionQuit));
156 putDirectFunction(globalExec(), new (globalExec()) JSFunction(globalExec(), this, functionStructure(), 0, Identifier(globalExec(), "gc"), functionGC));
157 putDirectFunction(globalExec(), new (globalExec()) JSFunction(globalExec(), this, functionStructure(), 1, Identifier(globalExec(), "version"), functionVersion));
158 putDirectFunction(globalExec(), new (globalExec()) JSFunction(globalExec(), this, functionStructure(), 1, Identifier(globalExec(), "run"), functionRun));
159 putDirectFunction(globalExec(), new (globalExec()) JSFunction(globalExec(), this, functionStructure(), 1, Identifier(globalExec(), "load"), functionLoad));
160 putDirectFunction(globalExec(), new (globalExec()) JSFunction(globalExec(), this, functionStructure(), 1, Identifier(globalExec(), "checkSyntax"), functionCheckSyntax));
161 putDirectFunction(globalExec(), new (globalExec()) JSFunction(globalExec(), this, functionStructure(), 0, Identifier(globalExec(), "readline"), functionReadline));
162
163#if ENABLE(SAMPLING_FLAGS)
164 putDirectFunction(globalExec(), new (globalExec()) JSFunction(globalExec(), this, functionStructure(), 1, Identifier(globalExec(), "setSamplingFlags"), functionSetSamplingFlags));
165 putDirectFunction(globalExec(), new (globalExec()) JSFunction(globalExec(), this, functionStructure(), 1, Identifier(globalExec(), "clearSamplingFlags"), functionClearSamplingFlags));
166#endif
167
168 JSObject* array = constructEmptyArray(globalExec());
169 for (size_t i = 0; i < arguments.size(); ++i)
170 array->put(globalExec(), i, jsString(globalExec(), arguments[i]));
171 putDirect(globalExec()->globalData(), Identifier(globalExec(), "arguments"), array);
172}
173
174EncodedJSValue JSC_HOST_CALL functionPrint(ExecState* exec)
175{
176 for (unsigned i = 0; i < exec->argumentCount(); ++i) {
177 if (i)
178 putchar(' ');
179
180 printf("%s", exec->argument(i).toString(exec).utf8().data());
181 }
182
183 putchar('\n');
184 fflush(stdout);
185 return JSValue::encode(jsUndefined());
186}
187
188EncodedJSValue JSC_HOST_CALL functionDebug(ExecState* exec)
189{
190 fprintf(stderr, "--> %s\n", exec->argument(0).toString(exec).utf8().data());
191 return JSValue::encode(jsUndefined());
192}
193
194EncodedJSValue JSC_HOST_CALL functionGC(ExecState* exec)
195{
196 JSLock lock(SilenceAssertionsOnly);
197 exec->heap()->collectAllGarbage();
198 return JSValue::encode(jsUndefined());
199}
200
201EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*)
202{
203 // We need this function for compatibility with the Mozilla JS tests but for now
204 // we don't actually do any version-specific handling
205 return JSValue::encode(jsUndefined());
206}
207
208EncodedJSValue JSC_HOST_CALL functionRun(ExecState* exec)
209{
210 UString fileName = exec->argument(0).toString(exec);
211 Vector<char> script;
212 if (!fillBufferWithContentsOfFile(fileName, script))
213 return JSValue::encode(throwError(exec, createError(exec, "Could not open file.")));
214
215 GlobalObject* globalObject = new (&exec->globalData()) GlobalObject(Vector<UString>());
216
217 StopWatch stopWatch;
218 stopWatch.start();
219 evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(script.data(), fileName));
220 stopWatch.stop();
221
222 return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
223}
224
225EncodedJSValue JSC_HOST_CALL functionLoad(ExecState* exec)
226{
227 UString fileName = exec->argument(0).toString(exec);
228 Vector<char> script;
229 if (!fillBufferWithContentsOfFile(fileName, script))
230 return JSValue::encode(throwError(exec, createError(exec, "Could not open file.")));
231
232 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
233 Completion result = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(script.data(), fileName));
234 if (result.complType() == Throw)
235 throwError(exec, result.value());
236 return JSValue::encode(result.value());
237}
238
239EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState* exec)
240{
241 UString fileName = exec->argument(0).toString(exec);
242 Vector<char> script;
243 if (!fillBufferWithContentsOfFile(fileName, script))
244 return JSValue::encode(throwError(exec, createError(exec, "Could not open file.")));
245
246 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
247
248 StopWatch stopWatch;
249 stopWatch.start();
250 Completion result = checkSyntax(globalObject->globalExec(), makeSource(script.data(), fileName));
251 stopWatch.stop();
252
253 if (result.complType() == Throw)
254 throwError(exec, result.value());
255 return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
256}
257
258#if ENABLE(SAMPLING_FLAGS)
259EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState* exec)
260{
261 for (unsigned i = 0; i < exec->argumentCount(); ++i) {
262 unsigned flag = static_cast<unsigned>(exec->argument(i).toNumber(exec));
263 if ((flag >= 1) && (flag <= 32))
264 SamplingFlags::setFlag(flag);
265 }
266 return JSValue::encode(jsNull());
267}
268
269EncodedJSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState* exec)
270{
271 for (unsigned i = 0; i < exec->argumentCount(); ++i) {
272 unsigned flag = static_cast<unsigned>(exec->argument(i).toNumber(exec));
273 if ((flag >= 1) && (flag <= 32))
274 SamplingFlags::clearFlag(flag);
275 }
276 return JSValue::encode(jsNull());
277}
278#endif
279
280EncodedJSValue JSC_HOST_CALL functionReadline(ExecState* exec)
281{
282 Vector<char, 256> line;
283 int c;
284 while ((c = getchar()) != EOF) {
285 // FIXME: Should we also break on \r?
286 if (c == '\n')
287 break;
288 line.append(c);
289 }
290 line.append('\0');
291 return JSValue::encode(jsString(exec, line.data()));
292}
293
294EncodedJSValue JSC_HOST_CALL functionQuit(ExecState* exec)
295{
296 // Technically, destroying the heap in the middle of JS execution is a no-no,
297 // but we want to maintain compatibility with the Mozilla test suite, so
298 // we pretend that execution has terminated to avoid ASSERTs, then tear down the heap.
299 exec->globalData().dynamicGlobalObject = 0;
300
301 cleanupGlobalData(&exec->globalData());
302 exit(EXIT_SUCCESS);
303
304#if COMPILER(MSVC) && OS(WINCE)
305 // Without this, Visual Studio will complain that this method does not return a value.
306 return JSValue::encode(jsUndefined());
307#endif
308}
309
310// Use SEH for Release builds only to get rid of the crash report dialog
311// (luckily the same tests fail in Release and Debug builds so far). Need to
312// be in a separate main function because the jscmain function requires object
313// unwinding.
314
315#if COMPILER(MSVC) && !defined(_DEBUG) && !OS(WINCE)
316#define TRY __try {
317#define EXCEPT(x) } __except (EXCEPTION_EXECUTE_HANDLER) { x; }
318#else
319#define TRY
320#define EXCEPT(x)
321#endif
322
323int jscmain(int argc, char** argv, JSGlobalData*);
324
325int main(int argc, char** argv)
326{
327#if defined(_DEBUG) && OS(WINDOWS)
328 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
329 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
330 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
331 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
332 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
333 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
334#endif
335
336#if COMPILER(MSVC) && !OS(WINCE)
337 timeBeginPeriod(1);
338#endif
339
340#if PLATFORM(QT)
341 QCoreApplication app(argc, argv);
342#endif
343
344 // Initialize JSC before getting JSGlobalData.
345 JSC::initializeThreading();
346
347 // We can't use destructors in the following code because it uses Windows
348 // Structured Exception Handling
349 int res = 0;
350 JSGlobalData* globalData = JSGlobalData::create(ThreadStackTypeLarge).leakRef();
351 TRY
352 res = jscmain(argc, argv, globalData);
353 EXCEPT(res = 3)
354
355 cleanupGlobalData(globalData);
356 return res;
357}
358
359static void cleanupGlobalData(JSGlobalData* globalData)
360{
361 JSLock lock(SilenceAssertionsOnly);
362 globalData->heap.destroy();
363 globalData->deref();
364}
365
366static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scripts, bool dump)
367{
368 UString script;
369 UString fileName;
370 Vector<char> scriptBuffer;
371
372 if (dump)
373 BytecodeGenerator::setDumpsGeneratedCode(true);
374
375 JSGlobalData& globalData = globalObject->globalData();
376
377#if ENABLE(SAMPLING_FLAGS)
378 SamplingFlags::start();
379#endif
380
381 bool success = true;
382 for (size_t i = 0; i < scripts.size(); i++) {
383 if (scripts[i].isFile) {
384 fileName = scripts[i].argument;
385 if (!fillBufferWithContentsOfFile(fileName, scriptBuffer))
386 return false; // fail early so we can catch missing files
387 script = scriptBuffer.data();
388 } else {
389 script = scripts[i].argument;
390 fileName = "[Command Line]";
391 }
392
393 globalData.startSampling();
394
395 Completion completion = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(script, fileName));
396 success = success && completion.complType() != Throw;
397 if (dump) {
398 if (completion.complType() == Throw)
399 printf("Exception: %s\n", completion.value().toString(globalObject->globalExec()).utf8().data());
400 else
401 printf("End: %s\n", completion.value().toString(globalObject->globalExec()).utf8().data());
402 }
403
404 globalData.stopSampling();
405 globalObject->globalExec()->clearException();
406 }
407
408#if ENABLE(SAMPLING_FLAGS)
409 SamplingFlags::stop();
410#endif
411 globalData.dumpSampleData(globalObject->globalExec());
412#if ENABLE(SAMPLING_COUNTERS)
413 AbstractSamplingCounter::dump();
414#endif
415#if ENABLE(REGEXP_TRACING)
416 globalData.dumpRegExpTrace();
417#endif
418 return success;
419}
420
421#define RUNNING_FROM_XCODE 0
422
423static void runInteractive(GlobalObject* globalObject)
424{
425 while (true) {
426#if HAVE(READLINE) && !RUNNING_FROM_XCODE
427 char* line = readline(interactivePrompt);
428 if (!line)
429 break;
430 if (line[0])
431 add_history(line);
432 Completion completion = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(line, interpreterName));
433 free(line);
434#else
435 printf("%s", interactivePrompt);
436 Vector<char, 256> line;
437 int c;
438 while ((c = getchar()) != EOF) {
439 // FIXME: Should we also break on \r?
440 if (c == '\n')
441 break;
442 line.append(c);
443 }
444 if (line.isEmpty())
445 break;
446 line.append('\0');
447 Completion completion = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(line.data(), interpreterName));
448#endif
449 if (completion.complType() == Throw)
450 printf("Exception: %s\n", completion.value().toString(globalObject->globalExec()).utf8().data());
451 else
452 printf("%s\n", completion.value().toString(globalObject->globalExec()).utf8().data());
453
454 globalObject->globalExec()->clearException();
455 }
456 printf("\n");
457}
458
459static NO_RETURN void printUsageStatement(JSGlobalData* globalData, bool help = false)
460{
461 fprintf(stderr, "Usage: jsc [options] [files] [-- arguments]\n");
462 fprintf(stderr, " -d Dumps bytecode (debug builds only)\n");
463 fprintf(stderr, " -e Evaluate argument as script code\n");
464 fprintf(stderr, " -f Specifies a source file (deprecated)\n");
465 fprintf(stderr, " -h|--help Prints this help message\n");
466 fprintf(stderr, " -i Enables interactive mode (default if no files are specified)\n");
467#if HAVE(SIGNAL_H)
468 fprintf(stderr, " -s Installs signal handlers that exit on a crash (Unix platforms only)\n");
469#endif
470
471 cleanupGlobalData(globalData);
472 exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
473}
474
475static void parseArguments(int argc, char** argv, Options& options, JSGlobalData* globalData)
476{
477 int i = 1;
478 for (; i < argc; ++i) {
479 const char* arg = argv[i];
480 if (!strcmp(arg, "-f")) {
481 if (++i == argc)
482 printUsageStatement(globalData);
483 options.scripts.append(Script(true, argv[i]));
484 continue;
485 }
486 if (!strcmp(arg, "-e")) {
487 if (++i == argc)
488 printUsageStatement(globalData);
489 options.scripts.append(Script(false, argv[i]));
490 continue;
491 }
492 if (!strcmp(arg, "-i")) {
493 options.interactive = true;
494 continue;
495 }
496 if (!strcmp(arg, "-d")) {
497 options.dump = true;
498 continue;
499 }
500 if (!strcmp(arg, "-s")) {
501#if HAVE(SIGNAL_H)
502 signal(SIGILL, _exit);
503 signal(SIGFPE, _exit);
504 signal(SIGBUS, _exit);
505 signal(SIGSEGV, _exit);
506#endif
507 continue;
508 }
509 if (!strcmp(arg, "--")) {
510 ++i;
511 break;
512 }
513 if (!strcmp(arg, "-h") || !strcmp(arg, "--help"))
514 printUsageStatement(globalData, true);
515 options.scripts.append(Script(true, argv[i]));
516 }
517
518 if (options.scripts.isEmpty())
519 options.interactive = true;
520
521 for (; i < argc; ++i)
522 options.arguments.append(argv[i]);
523}
524
525int jscmain(int argc, char** argv, JSGlobalData* globalData)
526{
527 JSLock lock(SilenceAssertionsOnly);
528
529 Options options;
530 parseArguments(argc, argv, options, globalData);
531
532 GlobalObject* globalObject = new (globalData) GlobalObject(options.arguments);
533 bool success = runWithScripts(globalObject, options.scripts, options.dump);
534 if (options.interactive && success)
535 runInteractive(globalObject);
536
537 return success ? 0 : 3;
538}
539
540static bool fillBufferWithContentsOfFile(const UString& fileName, Vector<char>& buffer)
541{
542 FILE* f = fopen(fileName.utf8().data(), "r");
543 if (!f) {
544 fprintf(stderr, "Could not open file: %s\n", fileName.utf8().data());
545 return false;
546 }
547
548 size_t bufferSize = 0;
549 size_t bufferCapacity = 1024;
550
551 buffer.resize(bufferCapacity);
552
553 while (!feof(f) && !ferror(f)) {
554 bufferSize += fread(buffer.data() + bufferSize, 1, bufferCapacity - bufferSize, f);
555 if (bufferSize == bufferCapacity) { // guarantees space for trailing '\0'
556 bufferCapacity *= 2;
557 buffer.resize(bufferCapacity);
558 }
559 }
560 fclose(f);
561 buffer[bufferSize] = '\0';
562
563 if (buffer[0] == '#' && buffer[1] == '!')
564 buffer[0] = buffer[1] = '/';
565
566 return true;
567}
Note: See TracBrowser for help on using the repository browser.