зеркало из https://github.com/mozilla/pjs.git
Implemented Formatters for output
This commit is contained in:
Родитель
5d892e7bf7
Коммит
f9ce82ae8e
151
js/js2/js2.cpp
151
js/js2/js2.cpp
|
@ -22,8 +22,6 @@
|
|||
// JS2 shell.
|
||||
//
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "world.h"
|
||||
#include "interpreter.h"
|
||||
|
||||
|
@ -31,80 +29,7 @@ namespace JS = JavaScript;
|
|||
using namespace JavaScript;
|
||||
|
||||
|
||||
#ifdef XP_MAC
|
||||
#ifdef XP_MAC_MPW
|
||||
/* Macintosh MPW replacements for the ANSI routines. These translate LF's to CR's because
|
||||
the MPW libraries supplied by Metrowerks don't do that for some reason. */
|
||||
static void translateLFtoCR(char *str, int length)
|
||||
{
|
||||
char *limit = str + length;
|
||||
while (str != limit) {
|
||||
if (*str == '\n')
|
||||
*str = '\r';
|
||||
str++;
|
||||
}
|
||||
}
|
||||
|
||||
int fputc(int c, FILE *file)
|
||||
{
|
||||
char buffer = c;
|
||||
if (buffer == '\n')
|
||||
buffer = '\r';
|
||||
return fwrite(&buffer, 1, 1, file);
|
||||
}
|
||||
|
||||
int fputs(const char *s, FILE *file)
|
||||
{
|
||||
char buffer[4096];
|
||||
int n = strlen(s);
|
||||
int extra = 0;
|
||||
|
||||
while (n > sizeof buffer) {
|
||||
memcpy(buffer, s, sizeof buffer);
|
||||
translateLFtoCR(buffer, sizeof buffer);
|
||||
extra += fwrite(buffer, 1, sizeof buffer, file);
|
||||
n -= sizeof buffer;
|
||||
s += sizeof buffer;
|
||||
}
|
||||
memcpy(buffer, s, n);
|
||||
translateLFtoCR(buffer, n);
|
||||
return extra + fwrite(buffer, 1, n, file);
|
||||
}
|
||||
|
||||
int fprintf(FILE* file, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
char smallBuffer[4096];
|
||||
int n;
|
||||
int bufferSize = sizeof smallBuffer;
|
||||
char *buffer = smallBuffer;
|
||||
int result;
|
||||
|
||||
va_start(args, format);
|
||||
n = vsnprintf(buffer, bufferSize, format, args);
|
||||
va_end(args);
|
||||
while (n < 0) {
|
||||
if (buffer != smallBuffer)
|
||||
free(buffer);
|
||||
bufferSize <<= 1;
|
||||
buffer = malloc(bufferSize);
|
||||
if (!buffer) {
|
||||
ASSERT(false);
|
||||
return 0;
|
||||
}
|
||||
va_start(args, format);
|
||||
n = vsnprintf(buffer, bufferSize, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
translateLFtoCR(buffer, n);
|
||||
result = fwrite(buffer, 1, n, file);
|
||||
if (buffer != smallBuffer)
|
||||
free(buffer);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
#else /* XP_MAC_MPW */
|
||||
#if defined(XP_MAC) && !defined(XP_MAC_MPW)
|
||||
#include <SIOUX.h>
|
||||
#include <MacTypes.h>
|
||||
|
||||
|
@ -118,65 +43,69 @@ static void initConsole(StringPtr consoleName, const char* startupMessage, int &
|
|||
// Set up a buffer for stderr (otherwise it's a pig).
|
||||
setvbuf(stderr, new char[BUFSIZ], _IOLBF, BUFSIZ);
|
||||
|
||||
std::cout << startupMessage;
|
||||
stdOut << startupMessage;
|
||||
|
||||
argc = 1;
|
||||
argv = mac_argv;
|
||||
}
|
||||
#endif /* XP_MAC_MPW */
|
||||
#endif /* XP_MAC */
|
||||
#endif
|
||||
|
||||
|
||||
// Interactively read a line from the input stream in and put it into s.
|
||||
static bool promptLine(istream &in, string &s, const char *prompt)
|
||||
// Return false if reached the end of input before reading anything.
|
||||
static bool promptLine(LineReader &inReader, string &s, const char *prompt)
|
||||
{
|
||||
std::cout << prompt;
|
||||
#ifdef XP_MAC_MPW
|
||||
/* Print a CR after the prompt because MPW grabs the entire line when entering an interactive command */
|
||||
std::cout << std::endl;
|
||||
#endif
|
||||
#ifndef _WIN32
|
||||
return std::getline(in, s) != 0;
|
||||
#else
|
||||
char buffer[256];
|
||||
bool result = fgets(buffer, sizeof(buffer), stdin) != 0;
|
||||
s = buffer;
|
||||
return result;
|
||||
#endif
|
||||
if (prompt) {
|
||||
stdOut << prompt;
|
||||
#ifdef XP_MAC_MPW
|
||||
// Print a CR after the prompt because MPW grabs the entire line when entering an interactive command.
|
||||
stdOut << '\n';
|
||||
#endif
|
||||
}
|
||||
return inReader.readLine(s) != 0;
|
||||
}
|
||||
|
||||
|
||||
static void readEvalPrint(istream &in, World &world)
|
||||
const bool showTokens = true;
|
||||
|
||||
static void readEvalPrint(FILE *in, World &world)
|
||||
{
|
||||
String buffer;
|
||||
string line;
|
||||
String sourceLocation = widenCString("console");
|
||||
LineReader inReader(in);
|
||||
|
||||
while (promptLine(in, line, buffer.empty() ? "js> " : "")) {
|
||||
if (!buffer.empty())
|
||||
buffer += uni::lf;
|
||||
while (promptLine(inReader, line, buffer.empty() ? "js> " : 0)) {
|
||||
appendChars(buffer, line.data(), line.size());
|
||||
if (!buffer.empty()) {
|
||||
try {
|
||||
Lexer l(world, buffer, sourceLocation);
|
||||
try {
|
||||
Arena a;
|
||||
Parser p(world, a, buffer, sourceLocation);
|
||||
|
||||
if (showTokens) {
|
||||
Lexer &l = p.lexer;
|
||||
while (true) {
|
||||
const Token &t = l.get(true);
|
||||
if (t.hasKind(Token::end))
|
||||
break;
|
||||
String out;
|
||||
out += ' ';
|
||||
t.print(out, true);
|
||||
showString(std::cout, out);
|
||||
stdOut << ' ';
|
||||
t.print(stdOut, true);
|
||||
}
|
||||
} catch (Exception &e) {
|
||||
std::cout << std::endl;
|
||||
showString(std::cout, e.fullMessage());
|
||||
} else {
|
||||
ExprNode *parseTree = p.parsePostfixExpression();
|
||||
}
|
||||
std::cout << std::endl;
|
||||
clear(buffer);
|
||||
stdOut << '\n';
|
||||
} catch (Exception &e) {
|
||||
// If we got a syntax error on the end of input, then wait for a continuation
|
||||
// of input rather than printing the error message.
|
||||
if (!(e.hasKind(Exception::syntaxError) && e.lineNum && e.pos == buffer.size() &&
|
||||
e.sourceFile == sourceLocation)) {
|
||||
stdOut << '\n' << e.fullMessage();
|
||||
clear(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
std::cout << std::endl;
|
||||
stdOut << '\n';
|
||||
#if 0
|
||||
do {
|
||||
bufp = buffer;
|
||||
|
@ -276,7 +205,7 @@ static int ProcessInputFile(JSContext *cx, JSObject *obj, char *filename)
|
|||
static int
|
||||
usage(void)
|
||||
{
|
||||
std::cerr << "usage: js [-s] [-w] [-v version] [-f scriptfile] [scriptfile] [scriptarg...]\n";
|
||||
stdErr << "usage: js [-s] [-w] [-v version] [-f scriptfile] [scriptfile] [scriptarg...]\n";
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
@ -474,7 +403,7 @@ int main(int argc, char **argv)
|
|||
testInterpreter(5);
|
||||
testICG(world);
|
||||
#endif
|
||||
readEvalPrint(std::cin, world);
|
||||
readEvalPrint(stdin, world);
|
||||
return 0;
|
||||
|
||||
//return ProcessArgs(argv + 1, argc - 1);
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cfloat>
|
||||
#include <algorithm>
|
||||
#include "numerics.h"
|
||||
|
||||
namespace JS = JavaScript;
|
||||
|
@ -2735,10 +2734,22 @@ size_t JS::doubleToBaseStr(char *buffer, double value, uint base)
|
|||
|
||||
|
||||
// A version of doubleToStr that appends to the end of String dst.
|
||||
void JS::printDouble(String &dst, double value, DToStrMode mode, int precision)
|
||||
// precision should not exceed 101.
|
||||
void JS::appendDouble(String &dst, double value, DToStrMode mode, int precision)
|
||||
{
|
||||
char buffer[dtosVariableBufferSize(101)];
|
||||
ASSERT(uint(precision) <= 101);
|
||||
|
||||
dst += doubleToStr(buffer, sizeof buffer, value, mode, precision);
|
||||
}
|
||||
|
||||
|
||||
// A version of doubleToStr that prints to Formatter f.
|
||||
// precision should not exceed 101.
|
||||
void JS::printDouble(Formatter &f, double value, DToStrMode mode, int precision)
|
||||
{
|
||||
char buffer[dtosVariableBufferSize(101)];
|
||||
ASSERT(uint(precision) <= 101);
|
||||
|
||||
f << doubleToStr(buffer, sizeof buffer, value, mode, precision);
|
||||
}
|
||||
|
|
|
@ -139,7 +139,9 @@ namespace JavaScript {
|
|||
|
||||
char *doubleToStr(char *buffer, size_t bufferSize, double value, DToStrMode mode, int precision);
|
||||
size_t doubleToBaseStr(char *buffer, double value, uint base);
|
||||
void printDouble(String &dst, double value, DToStrMode mode = dtosStandard, int precision = 0);
|
||||
inline String &operator+=(String &s, double value) {printDouble(s, value); return s;}
|
||||
void appendDouble(String &dst, double value, DToStrMode mode = dtosStandard, int precision = 0);
|
||||
inline String &operator+=(String &s, double value) {appendDouble(s, value); return s;}
|
||||
void printDouble(Formatter &f, double value, DToStrMode mode = dtosStandard, int precision = 0);
|
||||
inline Formatter &operator<<(Formatter &f, double value) {printDouble(f, value); return f;}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <iomanip>
|
||||
#include <algorithm>
|
||||
#include "utilities.h"
|
||||
|
||||
#ifdef WIN32
|
||||
|
@ -1563,7 +1562,7 @@ struct JS::Arena::DestructorEntry: JS::ArenaObject {
|
|||
|
||||
|
||||
// Construct an Arena that allocates memory in chunks of the given size.
|
||||
JS::Arena::Arena(size_t blockSize): blockSize(blockSize), freeBegin(0), freeEnd(0)
|
||||
JS::Arena::Arena(size_t blockSize): freeBegin(0), freeEnd(0), blockSize(blockSize), destructorEntries(0)
|
||||
{
|
||||
ASSERT(blockSize && !(blockSize & basicAlignment-1));
|
||||
rootDirectory.next = 0;
|
||||
|
@ -1691,56 +1690,300 @@ JS::String &JS::newArenaString(Arena &arena, const String &str)
|
|||
|
||||
|
||||
//
|
||||
// C++ I/O
|
||||
// Output
|
||||
//
|
||||
|
||||
#ifdef __GNUC__
|
||||
JS::SaveFormat::SaveFormat(ostream &) {}
|
||||
|
||||
JS::SaveFormat::~SaveFormat() {}
|
||||
#else
|
||||
JS::SaveFormat::SaveFormat(ostream &out): o(out), flags(out.flags()), fill(out.fill()) {}
|
||||
|
||||
JS::SaveFormat::~SaveFormat()
|
||||
{
|
||||
o.flags(flags);
|
||||
o.fill(fill);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Quotes for printing non-ASCII characters on an ASCII stream
|
||||
#ifdef XP_MAC
|
||||
const char beginUnprintable = char(0xC7);
|
||||
const char endUnprintable = char(0xC8);
|
||||
#else
|
||||
const char beginUnprintable = '{';
|
||||
const char endUnprintable = '}';
|
||||
#endif
|
||||
|
||||
void JS::showChar(ostream &out, char16 ch)
|
||||
{
|
||||
#ifdef XP_MAC_MPW
|
||||
if (ch == '\n')
|
||||
out << '\r';
|
||||
else
|
||||
#endif
|
||||
if (uchar16(ch) <= 0x7E && (uchar16(ch) >= ' ' || ch == '\n' || ch == '\t'))
|
||||
out << static_cast<char>(ch);
|
||||
else {
|
||||
SaveFormat sf(out);
|
||||
#ifdef __GNUC__
|
||||
out << beginUnprintable << std::hex << std::setw(4) << std::setfill('0') << (uint16)ch << endUnprintable;
|
||||
#else
|
||||
out << beginUnprintable << std::hex << std::uppercase << std::setw(4) << std::setfill('0') << (uint16)ch << endUnprintable;
|
||||
#endif
|
||||
// Macintosh MPW replacements for the ANSI routines. These translate LF's to CR's because
|
||||
// the MPW libraries supplied by Metrowerks don't do that for some reason.
|
||||
static void translateLFtoCR(char *begin, char *end)
|
||||
{
|
||||
while (begin != end) {
|
||||
if (*begin == '\n')
|
||||
*begin = '\r';
|
||||
++begin;
|
||||
}
|
||||
}
|
||||
|
||||
size_t JS::printChars(FILE *file, const char *begin, const char *end)
|
||||
{
|
||||
ASSERT(end >= begin);
|
||||
size_t n = static_cast<size_t>(end - begin);
|
||||
size_t extra = 0;
|
||||
char buffer[1024];
|
||||
|
||||
while (n > sizeof buffer) {
|
||||
memcpy(buffer, s, sizeof buffer);
|
||||
translateLFtoCR(buffer, buffer + sizeof buffer);
|
||||
extra += fwrite(buffer, 1, sizeof buffer, file);
|
||||
n -= sizeof buffer;
|
||||
s += sizeof buffer;
|
||||
}
|
||||
memcpy(buffer, s, n);
|
||||
translateLFtoCR(buffer, buffer + n);
|
||||
return extra + fwrite(buffer, 1, n, file);
|
||||
}
|
||||
|
||||
int std::fputc(int c, FILE *file)
|
||||
{
|
||||
char buffer = c;
|
||||
if (buffer == '\n')
|
||||
buffer = '\r';
|
||||
return fwrite(&buffer, 1, 1, file);
|
||||
}
|
||||
|
||||
int std::fputs(const char *s, FILE *file)
|
||||
{
|
||||
return static_cast<int>(printChars(file, s, s + strlen(s)));
|
||||
}
|
||||
|
||||
int std::fprintf(FILE* file, const char *format, ...)
|
||||
{
|
||||
Buffer<char, 1024> b;
|
||||
|
||||
while (true) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int n = vsnprintf(b.buffer, b.size, format, args);
|
||||
va_end(args);
|
||||
if (n >= 0 && n < b.size) {
|
||||
translateLFtoCR(b.buffer, b.buffer + n);
|
||||
return static_cast<int>(fwrite(b.buffer, 1, n, file));
|
||||
}
|
||||
b.expand(b.size*2);
|
||||
}
|
||||
}
|
||||
#endif // XP_MAC_MPW
|
||||
|
||||
|
||||
|
||||
static const printCharBufferSize = 64;
|
||||
|
||||
// Print ch count times.
|
||||
void JS::printChar(Formatter &f, char ch, int count)
|
||||
{
|
||||
char str[printCharBufferSize];
|
||||
|
||||
while (count > 0) {
|
||||
int c = count;
|
||||
if (c > printCharBufferSize)
|
||||
c = printCharBufferSize;
|
||||
count -= c;
|
||||
STD::memset(str, ch, static_cast<size_t>(count));
|
||||
printString(f, str, str+c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void JS::showString(ostream &out, const String &str)
|
||||
// Print ch count times.
|
||||
void JS::printChar(Formatter &f, char16 ch, int count)
|
||||
{
|
||||
showString(out, str.begin(), str.end());
|
||||
char16 str[printCharBufferSize];
|
||||
|
||||
while (count > 0) {
|
||||
int c = count;
|
||||
if (c > printCharBufferSize)
|
||||
c = printCharBufferSize;
|
||||
count -= c;
|
||||
char16 *strEnd = str + c;
|
||||
std::fill(str, strEnd, ch);
|
||||
printString(f, str, strEnd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Print i using the given formatting string, padding on the left with pad characters
|
||||
// to use at least nDigits characters.
|
||||
void JS::printNum(Formatter &f, uint32 i, int nDigits, char pad, const char *format)
|
||||
{
|
||||
char str[20];
|
||||
int n = sprintf(str, format, i);
|
||||
if (n < nDigits)
|
||||
printChar(f, pad, nDigits - n);
|
||||
printString(f, str, str+n);
|
||||
}
|
||||
|
||||
|
||||
// Print p as a pointer.
|
||||
void JS::printPtr(Formatter &f, void *p)
|
||||
{
|
||||
char str[20];
|
||||
int n = sprintf(str, "%p", p);
|
||||
printString(f, str, str+n);
|
||||
}
|
||||
|
||||
|
||||
// printf formats for printing non-ASCII characters on an ASCII stream
|
||||
#ifdef XP_MAC
|
||||
static const char unprintableFormat[] = "\xC7%.4X\xC8"; // Use angle quotes
|
||||
#elif defined _WIN32
|
||||
static const char unprintableFormat[] = "\xAB%.4X\xBB"; // Use angle quotes
|
||||
#else
|
||||
static const char unprintableFormat[] = "<%.4X>";
|
||||
#endif
|
||||
|
||||
|
||||
static const uint16 defaultFilterRanges[] = {
|
||||
0x00, 0x09, // Filter all control characters except \t and \n
|
||||
0x0B, 0x20,
|
||||
0x7F, 0x100, // Filter all non-ASCII characters
|
||||
0, 0
|
||||
};
|
||||
|
||||
JS::BitSet<256> JS::AsciiFileFormatter::defaultFilter(defaultFilterRanges);
|
||||
|
||||
|
||||
// Construct an AsciiFileFormatter using the given file and filter.
|
||||
// If the filter is nil, use the default filter.
|
||||
JS::AsciiFileFormatter::AsciiFileFormatter(FILE *file, BitSet<256> *filter):
|
||||
file(file), filter(filter ? *filter : defaultFilter)
|
||||
{
|
||||
filterEmpty = AsciiFileFormatter::filter.none();
|
||||
}
|
||||
|
||||
|
||||
// Write ch, escaping non-ASCII characters.
|
||||
void JS::AsciiFileFormatter::printChar8(char ch)
|
||||
{
|
||||
if (filterChar(ch))
|
||||
fprintf(file, unprintableFormat, static_cast<uchar>(ch));
|
||||
else
|
||||
fputc(ch, file);
|
||||
}
|
||||
|
||||
|
||||
// Write ch, escaping non-ASCII characters.
|
||||
void JS::AsciiFileFormatter::printChar16(char16 ch)
|
||||
{
|
||||
if (filterChar(ch))
|
||||
fprintf(file, unprintableFormat, char16Value(ch));
|
||||
else
|
||||
fputc(static_cast<char>(ch), file);
|
||||
}
|
||||
|
||||
|
||||
// Write the null-terminated string str, escaping non-ASCII characters.
|
||||
void JS::AsciiFileFormatter::printZStr8(const char *str)
|
||||
{
|
||||
if (filterEmpty)
|
||||
fputs(str, file);
|
||||
else
|
||||
printStr8(str, str + strlen(str));
|
||||
}
|
||||
|
||||
|
||||
// Write the string between strBegin and strEnd, escaping non-ASCII characters.
|
||||
void JS::AsciiFileFormatter::printStr8(const char *strBegin, const char *strEnd)
|
||||
{
|
||||
if (filterEmpty)
|
||||
printChars(file, strBegin, strEnd);
|
||||
else {
|
||||
ASSERT(strEnd >= strBegin);
|
||||
const char *p = strBegin;
|
||||
while (strBegin != strEnd) {
|
||||
char ch = *strBegin;
|
||||
if (filterChar(ch)) {
|
||||
if (p != strBegin) {
|
||||
printChars(file, p, strBegin);
|
||||
p = strBegin;
|
||||
}
|
||||
fprintf(file, unprintableFormat, static_cast<uchar>(ch));
|
||||
}
|
||||
++strBegin;
|
||||
}
|
||||
if (p != strBegin)
|
||||
printChars(file, p, strBegin);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Write the string between strBegin and strEnd, escaping non-ASCII characters.
|
||||
void JS::AsciiFileFormatter::printStr16(const char16 *strBegin, const char16 *strEnd)
|
||||
{
|
||||
char buffer[512];
|
||||
|
||||
ASSERT(strEnd >= strBegin);
|
||||
char *q = buffer;
|
||||
while (strBegin != strEnd) {
|
||||
char16 ch = *strBegin++;
|
||||
if (filterChar(ch)) {
|
||||
if (q != buffer) {
|
||||
printChars(file, buffer, q);
|
||||
q = buffer;
|
||||
}
|
||||
fprintf(file, unprintableFormat, char16Value(ch));
|
||||
} else {
|
||||
*q++ = static_cast<char>(ch);
|
||||
if (q == buffer + sizeof buffer) {
|
||||
printChars(file, buffer, buffer + sizeof buffer);
|
||||
q = buffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (q != buffer)
|
||||
printChars(file, buffer, q);
|
||||
}
|
||||
|
||||
|
||||
// Write the String s, escaping non-ASCII characters.
|
||||
void JS::AsciiFileFormatter::printString16(const String &s)
|
||||
{
|
||||
const char16 *begin = s.data();
|
||||
printStr16(begin, begin + s.size());
|
||||
}
|
||||
|
||||
|
||||
// Write the printf format using the supplied args, escaping non-ASCII characters.
|
||||
void JS::AsciiFileFormatter::printVFormat8(const char *format, va_list args)
|
||||
{
|
||||
Buffer<char, 1024> b;
|
||||
|
||||
while (true) {
|
||||
int n = vsnprintf(b.buffer, b.size, format, args);
|
||||
if (n >= 0 && n < b.size) {
|
||||
printStr8(b.buffer, b.buffer + n);
|
||||
return;
|
||||
}
|
||||
b.expand(b.size*2);
|
||||
}
|
||||
}
|
||||
|
||||
JS::AsciiFileFormatter JS::stdOut(stdout);
|
||||
JS::AsciiFileFormatter JS::stdErr(stderr);
|
||||
|
||||
|
||||
//
|
||||
// Input
|
||||
//
|
||||
|
||||
|
||||
// Read a line from the input file, including the trailing line break character.
|
||||
// Return the total number of characters read, which is str's length.
|
||||
// Translate <CR> and <CR><LF> sequences to <LF> characters; a <CR><LF> sequence
|
||||
// only counts as one character.
|
||||
size_t JS::LineReader::readLine(string &str)
|
||||
{
|
||||
int ch;
|
||||
bool oldCRWasLast = crWasLast;
|
||||
crWasLast = false;
|
||||
|
||||
str.resize(0);
|
||||
while ((ch = getc(in)) != EOF) {
|
||||
if (ch == '\n') {
|
||||
if (!str.size() && oldCRWasLast)
|
||||
continue;
|
||||
str += '\n';
|
||||
break;
|
||||
}
|
||||
if (ch == '\r') {
|
||||
crWasLast = true;
|
||||
str += '\n';
|
||||
break;
|
||||
}
|
||||
str += static_cast<char>(ch);
|
||||
}
|
||||
|
||||
return str.size();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1750,7 +1993,8 @@ void JS::showString(ostream &out, const String &str)
|
|||
|
||||
|
||||
static const char *const kindStrings[] = {
|
||||
"Syntax error" // SyntaxError
|
||||
"Syntax error", // syntaxError
|
||||
"Stack overflow" // stackOverflow
|
||||
};
|
||||
|
||||
// Return a null-terminated string describing the exception's kind.
|
||||
|
@ -1763,7 +2007,8 @@ const char *JS::Exception::kindString() const
|
|||
// Return the full error message.
|
||||
JS::String JS::Exception::fullMessage() const
|
||||
{
|
||||
String m(sourceFile);
|
||||
String m(widenCString("In "));
|
||||
m += sourceFile;
|
||||
if (lineNum) {
|
||||
char b[32];
|
||||
sprintf(b, ", line %d:\n", lineNum);
|
||||
|
@ -1779,6 +2024,7 @@ JS::String JS::Exception::fullMessage() const
|
|||
m += kindString();
|
||||
m += ": ";
|
||||
m += message;
|
||||
m += '\n';
|
||||
return m;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cfloat>
|
||||
#include <algorithm>
|
||||
#include "numerics.h"
|
||||
|
||||
namespace JS = JavaScript;
|
||||
|
@ -2735,10 +2734,22 @@ size_t JS::doubleToBaseStr(char *buffer, double value, uint base)
|
|||
|
||||
|
||||
// A version of doubleToStr that appends to the end of String dst.
|
||||
void JS::printDouble(String &dst, double value, DToStrMode mode, int precision)
|
||||
// precision should not exceed 101.
|
||||
void JS::appendDouble(String &dst, double value, DToStrMode mode, int precision)
|
||||
{
|
||||
char buffer[dtosVariableBufferSize(101)];
|
||||
ASSERT(uint(precision) <= 101);
|
||||
|
||||
dst += doubleToStr(buffer, sizeof buffer, value, mode, precision);
|
||||
}
|
||||
|
||||
|
||||
// A version of doubleToStr that prints to Formatter f.
|
||||
// precision should not exceed 101.
|
||||
void JS::printDouble(Formatter &f, double value, DToStrMode mode, int precision)
|
||||
{
|
||||
char buffer[dtosVariableBufferSize(101)];
|
||||
ASSERT(uint(precision) <= 101);
|
||||
|
||||
f << doubleToStr(buffer, sizeof buffer, value, mode, precision);
|
||||
}
|
||||
|
|
|
@ -139,7 +139,9 @@ namespace JavaScript {
|
|||
|
||||
char *doubleToStr(char *buffer, size_t bufferSize, double value, DToStrMode mode, int precision);
|
||||
size_t doubleToBaseStr(char *buffer, double value, uint base);
|
||||
void printDouble(String &dst, double value, DToStrMode mode = dtosStandard, int precision = 0);
|
||||
inline String &operator+=(String &s, double value) {printDouble(s, value); return s;}
|
||||
void appendDouble(String &dst, double value, DToStrMode mode = dtosStandard, int precision = 0);
|
||||
inline String &operator+=(String &s, double value) {appendDouble(s, value); return s;}
|
||||
void printDouble(Formatter &f, double value, DToStrMode mode = dtosStandard, int precision = 0);
|
||||
inline Formatter &operator<<(Formatter &f, double value) {printDouble(f, value); return f;}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <iomanip>
|
||||
#include <algorithm>
|
||||
#include "utilities.h"
|
||||
|
||||
#ifdef WIN32
|
||||
|
@ -1563,7 +1562,7 @@ struct JS::Arena::DestructorEntry: JS::ArenaObject {
|
|||
|
||||
|
||||
// Construct an Arena that allocates memory in chunks of the given size.
|
||||
JS::Arena::Arena(size_t blockSize): blockSize(blockSize), freeBegin(0), freeEnd(0)
|
||||
JS::Arena::Arena(size_t blockSize): freeBegin(0), freeEnd(0), blockSize(blockSize), destructorEntries(0)
|
||||
{
|
||||
ASSERT(blockSize && !(blockSize & basicAlignment-1));
|
||||
rootDirectory.next = 0;
|
||||
|
@ -1691,56 +1690,300 @@ JS::String &JS::newArenaString(Arena &arena, const String &str)
|
|||
|
||||
|
||||
//
|
||||
// C++ I/O
|
||||
// Output
|
||||
//
|
||||
|
||||
#ifdef __GNUC__
|
||||
JS::SaveFormat::SaveFormat(ostream &) {}
|
||||
|
||||
JS::SaveFormat::~SaveFormat() {}
|
||||
#else
|
||||
JS::SaveFormat::SaveFormat(ostream &out): o(out), flags(out.flags()), fill(out.fill()) {}
|
||||
|
||||
JS::SaveFormat::~SaveFormat()
|
||||
{
|
||||
o.flags(flags);
|
||||
o.fill(fill);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Quotes for printing non-ASCII characters on an ASCII stream
|
||||
#ifdef XP_MAC
|
||||
const char beginUnprintable = char(0xC7);
|
||||
const char endUnprintable = char(0xC8);
|
||||
#else
|
||||
const char beginUnprintable = '{';
|
||||
const char endUnprintable = '}';
|
||||
#endif
|
||||
|
||||
void JS::showChar(ostream &out, char16 ch)
|
||||
{
|
||||
#ifdef XP_MAC_MPW
|
||||
if (ch == '\n')
|
||||
out << '\r';
|
||||
else
|
||||
#endif
|
||||
if (uchar16(ch) <= 0x7E && (uchar16(ch) >= ' ' || ch == '\n' || ch == '\t'))
|
||||
out << static_cast<char>(ch);
|
||||
else {
|
||||
SaveFormat sf(out);
|
||||
#ifdef __GNUC__
|
||||
out << beginUnprintable << std::hex << std::setw(4) << std::setfill('0') << (uint16)ch << endUnprintable;
|
||||
#else
|
||||
out << beginUnprintable << std::hex << std::uppercase << std::setw(4) << std::setfill('0') << (uint16)ch << endUnprintable;
|
||||
#endif
|
||||
// Macintosh MPW replacements for the ANSI routines. These translate LF's to CR's because
|
||||
// the MPW libraries supplied by Metrowerks don't do that for some reason.
|
||||
static void translateLFtoCR(char *begin, char *end)
|
||||
{
|
||||
while (begin != end) {
|
||||
if (*begin == '\n')
|
||||
*begin = '\r';
|
||||
++begin;
|
||||
}
|
||||
}
|
||||
|
||||
size_t JS::printChars(FILE *file, const char *begin, const char *end)
|
||||
{
|
||||
ASSERT(end >= begin);
|
||||
size_t n = static_cast<size_t>(end - begin);
|
||||
size_t extra = 0;
|
||||
char buffer[1024];
|
||||
|
||||
while (n > sizeof buffer) {
|
||||
memcpy(buffer, s, sizeof buffer);
|
||||
translateLFtoCR(buffer, buffer + sizeof buffer);
|
||||
extra += fwrite(buffer, 1, sizeof buffer, file);
|
||||
n -= sizeof buffer;
|
||||
s += sizeof buffer;
|
||||
}
|
||||
memcpy(buffer, s, n);
|
||||
translateLFtoCR(buffer, buffer + n);
|
||||
return extra + fwrite(buffer, 1, n, file);
|
||||
}
|
||||
|
||||
int std::fputc(int c, FILE *file)
|
||||
{
|
||||
char buffer = c;
|
||||
if (buffer == '\n')
|
||||
buffer = '\r';
|
||||
return fwrite(&buffer, 1, 1, file);
|
||||
}
|
||||
|
||||
int std::fputs(const char *s, FILE *file)
|
||||
{
|
||||
return static_cast<int>(printChars(file, s, s + strlen(s)));
|
||||
}
|
||||
|
||||
int std::fprintf(FILE* file, const char *format, ...)
|
||||
{
|
||||
Buffer<char, 1024> b;
|
||||
|
||||
while (true) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int n = vsnprintf(b.buffer, b.size, format, args);
|
||||
va_end(args);
|
||||
if (n >= 0 && n < b.size) {
|
||||
translateLFtoCR(b.buffer, b.buffer + n);
|
||||
return static_cast<int>(fwrite(b.buffer, 1, n, file));
|
||||
}
|
||||
b.expand(b.size*2);
|
||||
}
|
||||
}
|
||||
#endif // XP_MAC_MPW
|
||||
|
||||
|
||||
|
||||
static const printCharBufferSize = 64;
|
||||
|
||||
// Print ch count times.
|
||||
void JS::printChar(Formatter &f, char ch, int count)
|
||||
{
|
||||
char str[printCharBufferSize];
|
||||
|
||||
while (count > 0) {
|
||||
int c = count;
|
||||
if (c > printCharBufferSize)
|
||||
c = printCharBufferSize;
|
||||
count -= c;
|
||||
STD::memset(str, ch, static_cast<size_t>(count));
|
||||
printString(f, str, str+c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void JS::showString(ostream &out, const String &str)
|
||||
// Print ch count times.
|
||||
void JS::printChar(Formatter &f, char16 ch, int count)
|
||||
{
|
||||
showString(out, str.begin(), str.end());
|
||||
char16 str[printCharBufferSize];
|
||||
|
||||
while (count > 0) {
|
||||
int c = count;
|
||||
if (c > printCharBufferSize)
|
||||
c = printCharBufferSize;
|
||||
count -= c;
|
||||
char16 *strEnd = str + c;
|
||||
std::fill(str, strEnd, ch);
|
||||
printString(f, str, strEnd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Print i using the given formatting string, padding on the left with pad characters
|
||||
// to use at least nDigits characters.
|
||||
void JS::printNum(Formatter &f, uint32 i, int nDigits, char pad, const char *format)
|
||||
{
|
||||
char str[20];
|
||||
int n = sprintf(str, format, i);
|
||||
if (n < nDigits)
|
||||
printChar(f, pad, nDigits - n);
|
||||
printString(f, str, str+n);
|
||||
}
|
||||
|
||||
|
||||
// Print p as a pointer.
|
||||
void JS::printPtr(Formatter &f, void *p)
|
||||
{
|
||||
char str[20];
|
||||
int n = sprintf(str, "%p", p);
|
||||
printString(f, str, str+n);
|
||||
}
|
||||
|
||||
|
||||
// printf formats for printing non-ASCII characters on an ASCII stream
|
||||
#ifdef XP_MAC
|
||||
static const char unprintableFormat[] = "\xC7%.4X\xC8"; // Use angle quotes
|
||||
#elif defined _WIN32
|
||||
static const char unprintableFormat[] = "\xAB%.4X\xBB"; // Use angle quotes
|
||||
#else
|
||||
static const char unprintableFormat[] = "<%.4X>";
|
||||
#endif
|
||||
|
||||
|
||||
static const uint16 defaultFilterRanges[] = {
|
||||
0x00, 0x09, // Filter all control characters except \t and \n
|
||||
0x0B, 0x20,
|
||||
0x7F, 0x100, // Filter all non-ASCII characters
|
||||
0, 0
|
||||
};
|
||||
|
||||
JS::BitSet<256> JS::AsciiFileFormatter::defaultFilter(defaultFilterRanges);
|
||||
|
||||
|
||||
// Construct an AsciiFileFormatter using the given file and filter.
|
||||
// If the filter is nil, use the default filter.
|
||||
JS::AsciiFileFormatter::AsciiFileFormatter(FILE *file, BitSet<256> *filter):
|
||||
file(file), filter(filter ? *filter : defaultFilter)
|
||||
{
|
||||
filterEmpty = AsciiFileFormatter::filter.none();
|
||||
}
|
||||
|
||||
|
||||
// Write ch, escaping non-ASCII characters.
|
||||
void JS::AsciiFileFormatter::printChar8(char ch)
|
||||
{
|
||||
if (filterChar(ch))
|
||||
fprintf(file, unprintableFormat, static_cast<uchar>(ch));
|
||||
else
|
||||
fputc(ch, file);
|
||||
}
|
||||
|
||||
|
||||
// Write ch, escaping non-ASCII characters.
|
||||
void JS::AsciiFileFormatter::printChar16(char16 ch)
|
||||
{
|
||||
if (filterChar(ch))
|
||||
fprintf(file, unprintableFormat, char16Value(ch));
|
||||
else
|
||||
fputc(static_cast<char>(ch), file);
|
||||
}
|
||||
|
||||
|
||||
// Write the null-terminated string str, escaping non-ASCII characters.
|
||||
void JS::AsciiFileFormatter::printZStr8(const char *str)
|
||||
{
|
||||
if (filterEmpty)
|
||||
fputs(str, file);
|
||||
else
|
||||
printStr8(str, str + strlen(str));
|
||||
}
|
||||
|
||||
|
||||
// Write the string between strBegin and strEnd, escaping non-ASCII characters.
|
||||
void JS::AsciiFileFormatter::printStr8(const char *strBegin, const char *strEnd)
|
||||
{
|
||||
if (filterEmpty)
|
||||
printChars(file, strBegin, strEnd);
|
||||
else {
|
||||
ASSERT(strEnd >= strBegin);
|
||||
const char *p = strBegin;
|
||||
while (strBegin != strEnd) {
|
||||
char ch = *strBegin;
|
||||
if (filterChar(ch)) {
|
||||
if (p != strBegin) {
|
||||
printChars(file, p, strBegin);
|
||||
p = strBegin;
|
||||
}
|
||||
fprintf(file, unprintableFormat, static_cast<uchar>(ch));
|
||||
}
|
||||
++strBegin;
|
||||
}
|
||||
if (p != strBegin)
|
||||
printChars(file, p, strBegin);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Write the string between strBegin and strEnd, escaping non-ASCII characters.
|
||||
void JS::AsciiFileFormatter::printStr16(const char16 *strBegin, const char16 *strEnd)
|
||||
{
|
||||
char buffer[512];
|
||||
|
||||
ASSERT(strEnd >= strBegin);
|
||||
char *q = buffer;
|
||||
while (strBegin != strEnd) {
|
||||
char16 ch = *strBegin++;
|
||||
if (filterChar(ch)) {
|
||||
if (q != buffer) {
|
||||
printChars(file, buffer, q);
|
||||
q = buffer;
|
||||
}
|
||||
fprintf(file, unprintableFormat, char16Value(ch));
|
||||
} else {
|
||||
*q++ = static_cast<char>(ch);
|
||||
if (q == buffer + sizeof buffer) {
|
||||
printChars(file, buffer, buffer + sizeof buffer);
|
||||
q = buffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (q != buffer)
|
||||
printChars(file, buffer, q);
|
||||
}
|
||||
|
||||
|
||||
// Write the String s, escaping non-ASCII characters.
|
||||
void JS::AsciiFileFormatter::printString16(const String &s)
|
||||
{
|
||||
const char16 *begin = s.data();
|
||||
printStr16(begin, begin + s.size());
|
||||
}
|
||||
|
||||
|
||||
// Write the printf format using the supplied args, escaping non-ASCII characters.
|
||||
void JS::AsciiFileFormatter::printVFormat8(const char *format, va_list args)
|
||||
{
|
||||
Buffer<char, 1024> b;
|
||||
|
||||
while (true) {
|
||||
int n = vsnprintf(b.buffer, b.size, format, args);
|
||||
if (n >= 0 && n < b.size) {
|
||||
printStr8(b.buffer, b.buffer + n);
|
||||
return;
|
||||
}
|
||||
b.expand(b.size*2);
|
||||
}
|
||||
}
|
||||
|
||||
JS::AsciiFileFormatter JS::stdOut(stdout);
|
||||
JS::AsciiFileFormatter JS::stdErr(stderr);
|
||||
|
||||
|
||||
//
|
||||
// Input
|
||||
//
|
||||
|
||||
|
||||
// Read a line from the input file, including the trailing line break character.
|
||||
// Return the total number of characters read, which is str's length.
|
||||
// Translate <CR> and <CR><LF> sequences to <LF> characters; a <CR><LF> sequence
|
||||
// only counts as one character.
|
||||
size_t JS::LineReader::readLine(string &str)
|
||||
{
|
||||
int ch;
|
||||
bool oldCRWasLast = crWasLast;
|
||||
crWasLast = false;
|
||||
|
||||
str.resize(0);
|
||||
while ((ch = getc(in)) != EOF) {
|
||||
if (ch == '\n') {
|
||||
if (!str.size() && oldCRWasLast)
|
||||
continue;
|
||||
str += '\n';
|
||||
break;
|
||||
}
|
||||
if (ch == '\r') {
|
||||
crWasLast = true;
|
||||
str += '\n';
|
||||
break;
|
||||
}
|
||||
str += static_cast<char>(ch);
|
||||
}
|
||||
|
||||
return str.size();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1750,7 +1993,8 @@ void JS::showString(ostream &out, const String &str)
|
|||
|
||||
|
||||
static const char *const kindStrings[] = {
|
||||
"Syntax error" // SyntaxError
|
||||
"Syntax error", // syntaxError
|
||||
"Stack overflow" // stackOverflow
|
||||
};
|
||||
|
||||
// Return a null-terminated string describing the exception's kind.
|
||||
|
@ -1763,7 +2007,8 @@ const char *JS::Exception::kindString() const
|
|||
// Return the full error message.
|
||||
JS::String JS::Exception::fullMessage() const
|
||||
{
|
||||
String m(sourceFile);
|
||||
String m(widenCString("In "));
|
||||
m += sourceFile;
|
||||
if (lineNum) {
|
||||
char b[32];
|
||||
sprintf(b, ", line %d:\n", lineNum);
|
||||
|
@ -1779,6 +2024,7 @@ JS::String JS::Exception::fullMessage() const
|
|||
m += kindString();
|
||||
m += ": ";
|
||||
m += message;
|
||||
m += '\n';
|
||||
return m;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,8 +22,6 @@
|
|||
// JS2 shell.
|
||||
//
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "world.h"
|
||||
#include "interpreter.h"
|
||||
|
||||
|
@ -31,80 +29,7 @@ namespace JS = JavaScript;
|
|||
using namespace JavaScript;
|
||||
|
||||
|
||||
#ifdef XP_MAC
|
||||
#ifdef XP_MAC_MPW
|
||||
/* Macintosh MPW replacements for the ANSI routines. These translate LF's to CR's because
|
||||
the MPW libraries supplied by Metrowerks don't do that for some reason. */
|
||||
static void translateLFtoCR(char *str, int length)
|
||||
{
|
||||
char *limit = str + length;
|
||||
while (str != limit) {
|
||||
if (*str == '\n')
|
||||
*str = '\r';
|
||||
str++;
|
||||
}
|
||||
}
|
||||
|
||||
int fputc(int c, FILE *file)
|
||||
{
|
||||
char buffer = c;
|
||||
if (buffer == '\n')
|
||||
buffer = '\r';
|
||||
return fwrite(&buffer, 1, 1, file);
|
||||
}
|
||||
|
||||
int fputs(const char *s, FILE *file)
|
||||
{
|
||||
char buffer[4096];
|
||||
int n = strlen(s);
|
||||
int extra = 0;
|
||||
|
||||
while (n > sizeof buffer) {
|
||||
memcpy(buffer, s, sizeof buffer);
|
||||
translateLFtoCR(buffer, sizeof buffer);
|
||||
extra += fwrite(buffer, 1, sizeof buffer, file);
|
||||
n -= sizeof buffer;
|
||||
s += sizeof buffer;
|
||||
}
|
||||
memcpy(buffer, s, n);
|
||||
translateLFtoCR(buffer, n);
|
||||
return extra + fwrite(buffer, 1, n, file);
|
||||
}
|
||||
|
||||
int fprintf(FILE* file, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
char smallBuffer[4096];
|
||||
int n;
|
||||
int bufferSize = sizeof smallBuffer;
|
||||
char *buffer = smallBuffer;
|
||||
int result;
|
||||
|
||||
va_start(args, format);
|
||||
n = vsnprintf(buffer, bufferSize, format, args);
|
||||
va_end(args);
|
||||
while (n < 0) {
|
||||
if (buffer != smallBuffer)
|
||||
free(buffer);
|
||||
bufferSize <<= 1;
|
||||
buffer = malloc(bufferSize);
|
||||
if (!buffer) {
|
||||
ASSERT(false);
|
||||
return 0;
|
||||
}
|
||||
va_start(args, format);
|
||||
n = vsnprintf(buffer, bufferSize, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
translateLFtoCR(buffer, n);
|
||||
result = fwrite(buffer, 1, n, file);
|
||||
if (buffer != smallBuffer)
|
||||
free(buffer);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
#else /* XP_MAC_MPW */
|
||||
#if defined(XP_MAC) && !defined(XP_MAC_MPW)
|
||||
#include <SIOUX.h>
|
||||
#include <MacTypes.h>
|
||||
|
||||
|
@ -118,65 +43,69 @@ static void initConsole(StringPtr consoleName, const char* startupMessage, int &
|
|||
// Set up a buffer for stderr (otherwise it's a pig).
|
||||
setvbuf(stderr, new char[BUFSIZ], _IOLBF, BUFSIZ);
|
||||
|
||||
std::cout << startupMessage;
|
||||
stdOut << startupMessage;
|
||||
|
||||
argc = 1;
|
||||
argv = mac_argv;
|
||||
}
|
||||
#endif /* XP_MAC_MPW */
|
||||
#endif /* XP_MAC */
|
||||
#endif
|
||||
|
||||
|
||||
// Interactively read a line from the input stream in and put it into s.
|
||||
static bool promptLine(istream &in, string &s, const char *prompt)
|
||||
// Return false if reached the end of input before reading anything.
|
||||
static bool promptLine(LineReader &inReader, string &s, const char *prompt)
|
||||
{
|
||||
std::cout << prompt;
|
||||
#ifdef XP_MAC_MPW
|
||||
/* Print a CR after the prompt because MPW grabs the entire line when entering an interactive command */
|
||||
std::cout << std::endl;
|
||||
#endif
|
||||
#ifndef _WIN32
|
||||
return std::getline(in, s) != 0;
|
||||
#else
|
||||
char buffer[256];
|
||||
bool result = fgets(buffer, sizeof(buffer), stdin) != 0;
|
||||
s = buffer;
|
||||
return result;
|
||||
#endif
|
||||
if (prompt) {
|
||||
stdOut << prompt;
|
||||
#ifdef XP_MAC_MPW
|
||||
// Print a CR after the prompt because MPW grabs the entire line when entering an interactive command.
|
||||
stdOut << '\n';
|
||||
#endif
|
||||
}
|
||||
return inReader.readLine(s) != 0;
|
||||
}
|
||||
|
||||
|
||||
static void readEvalPrint(istream &in, World &world)
|
||||
const bool showTokens = true;
|
||||
|
||||
static void readEvalPrint(FILE *in, World &world)
|
||||
{
|
||||
String buffer;
|
||||
string line;
|
||||
String sourceLocation = widenCString("console");
|
||||
LineReader inReader(in);
|
||||
|
||||
while (promptLine(in, line, buffer.empty() ? "js> " : "")) {
|
||||
if (!buffer.empty())
|
||||
buffer += uni::lf;
|
||||
while (promptLine(inReader, line, buffer.empty() ? "js> " : 0)) {
|
||||
appendChars(buffer, line.data(), line.size());
|
||||
if (!buffer.empty()) {
|
||||
try {
|
||||
Lexer l(world, buffer, sourceLocation);
|
||||
try {
|
||||
Arena a;
|
||||
Parser p(world, a, buffer, sourceLocation);
|
||||
|
||||
if (showTokens) {
|
||||
Lexer &l = p.lexer;
|
||||
while (true) {
|
||||
const Token &t = l.get(true);
|
||||
if (t.hasKind(Token::end))
|
||||
break;
|
||||
String out;
|
||||
out += ' ';
|
||||
t.print(out, true);
|
||||
showString(std::cout, out);
|
||||
stdOut << ' ';
|
||||
t.print(stdOut, true);
|
||||
}
|
||||
} catch (Exception &e) {
|
||||
std::cout << std::endl;
|
||||
showString(std::cout, e.fullMessage());
|
||||
} else {
|
||||
ExprNode *parseTree = p.parsePostfixExpression();
|
||||
}
|
||||
std::cout << std::endl;
|
||||
clear(buffer);
|
||||
stdOut << '\n';
|
||||
} catch (Exception &e) {
|
||||
// If we got a syntax error on the end of input, then wait for a continuation
|
||||
// of input rather than printing the error message.
|
||||
if (!(e.hasKind(Exception::syntaxError) && e.lineNum && e.pos == buffer.size() &&
|
||||
e.sourceFile == sourceLocation)) {
|
||||
stdOut << '\n' << e.fullMessage();
|
||||
clear(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
std::cout << std::endl;
|
||||
stdOut << '\n';
|
||||
#if 0
|
||||
do {
|
||||
bufp = buffer;
|
||||
|
@ -276,7 +205,7 @@ static int ProcessInputFile(JSContext *cx, JSObject *obj, char *filename)
|
|||
static int
|
||||
usage(void)
|
||||
{
|
||||
std::cerr << "usage: js [-s] [-w] [-v version] [-f scriptfile] [scriptfile] [scriptarg...]\n";
|
||||
stdErr << "usage: js [-s] [-w] [-v version] [-f scriptfile] [scriptfile] [scriptarg...]\n";
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
@ -474,7 +403,7 @@ int main(int argc, char **argv)
|
|||
testInterpreter(5);
|
||||
testICG(world);
|
||||
#endif
|
||||
readEvalPrint(std::cin, world);
|
||||
readEvalPrint(stdin, world);
|
||||
return 0;
|
||||
|
||||
//return ProcessArgs(argv + 1, argc - 1);
|
||||
|
|
Загрузка…
Ссылка в новой задаче