Bug 319719: JS scanner checks for keywords using pregenerated C source

avoiding the cost of atomizing keyword strings. This is an updated version
of the previous rather bad commit to address Makefile issues. r=brendan
This commit is contained in:
igor%mir2.org 2006-01-26 08:47:51 +00:00
parent 7be74bd85e
commit 581ca02192
18 changed files with 767 additions and 196 deletions

View File

@ -104,6 +104,7 @@ CSRCS = \
EXPORTS = \
jsautocfg.h \
jsautokw.h \
js.msg \
jsapi.h \
jsarray.h \
@ -193,6 +194,11 @@ JSJAVA_CFLAGS = \
-I$(topsrcdir)/sun-java/include \
$(JSJAVA_STUBHEADERS)
# Define keyword generator before rules.mk, see bug 323979 comment 50
HOST_SIMPLE_PROGRAMS += host_jskwgen$(HOST_BIN_SUFFIX)
GARBAGE += jsautokw.h host_jskwgen$(HOST_BIN_SUFFIX)
include $(topsrcdir)/config/rules.mk
DEFINES += -DEXPORT_JS_API
@ -392,3 +398,8 @@ jscpucfg$(HOST_BIN_SUFFIX): jscpucfg.c Makefile.in
endif
endif
# Extra dependancies and rules for keyword switch code
jsscan.$(OBJ_SUFFIX): jsautokw.h jskeyword.tbl
jsautokw.h: host_jskwgen$(HOST_BIN_SUFFIX) jskeyword.tbl
$< $@

View File

@ -64,6 +64,9 @@ else
OTHER_LIBS += -Lfdlibm/$(OBJDIR) -lfdm
endif
# Look in OBJDIR to find jsautocfg.h and jsautokw.h
INCLUDES += -I$(OBJDIR)
ifdef JS_THREADSAFE
DEFINES += -DJS_THREADSAFE
INCLUDES += -I../../dist/$(OBJDIR)/include
@ -120,9 +123,9 @@ endif
#
# Server-related changes :
#
ifdef NES40
DEFINES += -DNES40
endif
ifdef NES40
DEFINES += -DNES40
endif
#
# Line editing support.
@ -203,11 +206,13 @@ OTHER_HFILES = \
jsopcode.tbl \
js.msg \
jsshell.msg \
jskeyword.tbl \
$(NULL)
ifndef PREBUILT_CPUCFG
OTHER_HFILES += $(OBJDIR)/jsautocfg.h
endif
OTHER_HFILES += $(OBJDIR)/jsautokw.h
HFILES = $(JS_HFILES) $(API_HFILES) $(OTHER_HFILES)
@ -255,14 +260,14 @@ FDLIBM_LIBRARY = fdlibm/$(OBJDIR)/fdlibm.lib
else
FDLIBM_LIBRARY = fdlibm/$(OBJDIR)/libfdm.a
endif
JSMATH_PRELINK = $(OBJDIR)/jsmathtemp.o
JSMATH_PRELINK = $(OBJDIR)/jsmathtemp.$(OBJ_SUFFIX)
# Flag for incremental linking
DASH_R = -r
ifeq ($(OS_ARCH),QNX)
ifneq ($(OS_TARGET),NTO)
# Don't use wildcard here, because we only want this resolved at link time.
OBJS += fdlibm/*.o
OBJS += fdlibm/*.$(OBJ_SUFFIX)
endif
endif
@ -303,6 +308,33 @@ include jsconfig.mk
nsinstall-target:
cd ../../config; $(MAKE) OBJDIR=$(OBJDIR) OBJDIR_NAME=$(OBJDIR)
#
# Rules for keyword switch generation
#
GARBAGE += $(OBJDIR)/jsautokw.h $(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX)
GARBAGE += $(OBJDIR)/jskwgen.$(OBJ_SUFFIX)
$(OBJDIR)/jsscan.$(OBJ_SUFFIX): $(OBJDIR)/jsautokw.h jskeyword.tbl
$(OBJDIR)/jskwgen.$(OBJ_SUFFIX): jskwgen.c jskeyword.tbl
$(OBJDIR)/jsautokw.h: $(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX) jskeyword.tbl
$(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX) $@
ifdef USE_MSVC
$(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX): $(OBJDIR)/jskwgen.$(OBJ_SUFFIX)
link.exe -out:"$@" $(EXE_LINK_FLAGS) $^
else
$(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX): $(OBJDIR)/jskwgen.$(OBJ_SUFFIX)
$(CC) -o $@ $(CFLAGS) $(LDFLAGS) $^
endif
#
# JS shell executable
#
ifdef USE_MSVC
$(PROGRAM): $(PROG_OBJS) $(LIBRARY) $(FDLIBM_LIBRARY)
link.exe -out:"$@" $(EXE_LINK_FLAGS) $^
@ -327,15 +359,11 @@ $(OBJDIR)/jsautocfg.h: $(OBJDIR)/jscpucfg
$(OBJDIR)/jscpucfg: $(OBJDIR)/jscpucfg.o
$(CC) -o $@ $(OBJDIR)/jscpucfg.o
# Look in OBJDIR to find jsautocfg.h
INCLUDES += -I$(OBJDIR)
# Add to TARGETS for clobber rule
TARGETS += $(OBJDIR)/jsautocfg.h $(OBJDIR)/jscpucfg \
$(OBJDIR)/jscpucfg.o $(OBJDIR)/jsmathtemp.o
endif
# special rule for jsmath.o since we want to incrementally link
# against fdlibm to pull in only what is needed
$(OBJDIR)/jsmath.o: jsmath.c jsmath.h jslibmath.h $(FDLIBM_LIBRARY)
@ -348,7 +376,7 @@ endif
ifeq ($(OS_ARCH),QNX)
ifneq ($(OS_TARGET),NTO)
@cp $(JSMATH_PRELINK) $@
else
else
$(LD) $(DASH_R) -o $@ $(JSMATH_PRELINK) $(FDLIBM_LIBRARY)
endif
else

View File

@ -149,6 +149,22 @@ CLASSPATH = $(JDK)/lib/classes.zip$(SEP)$(CLASSDIR)/$(OBJDIR)
include $(DEPTH)/config/$(OS_CONFIG).mk
ifndef OBJ_SUFFIX
ifdef USE_MSVC
OBJ_SUFFIX = obj
else
OBJ_SUFFIX = o
endif
endif
ifndef HOST_BIN_SUFFIX
ifeq ($(OS_ARCH),WINNT)
HOST_BIN_SUFFIX = .exe
else
HOST_BIN_SUFFIX =
endif
endif
# Name of the binary code directories
ifdef BUILD_IDG
OBJDIR = $(OS_CONFIG)$(OBJDIR_TAG).OBJD

View File

@ -637,7 +637,7 @@ JS_GetTypeName(JSContext *cx, JSType type)
{
if ((uintN)type >= (uintN)JSTYPE_LIMIT)
return NULL;
return js_type_str[type];
return js_type_strs[type];
}
/************************************************************************/

View File

@ -71,7 +71,7 @@ extern const char js_Error_str[]; /* trivial, from jsexn.h */
* Keep this in sync with jspubtd.h -- an assertion below will insist that
* its length match the JSType enum's JSTYPE_LIMIT limit value.
*/
const char *js_type_str[] = {
const char *js_type_strs[] = {
"undefined",
js_object_str,
"function",
@ -82,7 +82,7 @@ const char *js_type_str[] = {
"xml",
};
const char *js_boolean_str[] = {
const char *js_boolean_strs[] = {
js_false_str,
js_true_str
};
@ -122,7 +122,6 @@ const char js_name_str[] = "name";
const char js_noSuchMethod_str[] = "__noSuchMethod__";
const char js_object_str[] = "object";
const char js_parent_str[] = "__parent__";
const char js_private_str[] = "private";
const char js_proto_str[] = "__proto__";
const char js_setter_str[] = "setter";
const char js_set_str[] = "set";
@ -294,9 +293,9 @@ js_InitPinnedAtoms(JSContext *cx, JSAtomState *state)
return JS_FALSE; \
JS_END_MACRO
JS_ASSERT(sizeof js_type_str / sizeof js_type_str[0] == JSTYPE_LIMIT);
JS_ASSERT(sizeof js_type_strs / sizeof js_type_strs[0] == JSTYPE_LIMIT);
for (i = 0; i < JSTYPE_LIMIT; i++)
FROB(typeAtoms[i], js_type_str[i]);
FROB(typeAtoms[i], js_type_strs[i]);
FROB(booleanAtoms[0], js_false_str);
FROB(booleanAtoms[1], js_true_str);

View File

@ -63,8 +63,8 @@ JS_BEGIN_EXTERN_C
#define ATOM_TMPSTR 0x80 /* internal, to avoid extra string */
struct JSAtom {
JSHashEntry entry; /* key is jsval, value keyword info or
unhidden atom if ATOM_HIDDEN */
JSHashEntry entry; /* key is jsval or unhidden atom
if ATOM_HIDDEN */
uint32 flags; /* pinned, interned, and mark flags */
jsatomid number; /* atom serial number and hash code */
};
@ -89,9 +89,6 @@ struct JSAtom {
extern JS_FRIEND_API(const char *)
js_AtomToPrintableString(JSContext *cx, JSAtom *atom);
#define ATOM_KEYWORD(atom) ((struct keyword *)(atom)->entry.value)
#define ATOM_SET_KEYWORD(atom,kw) ((atom)->entry.value = (kw))
struct JSAtomListElement {
JSHashEntry entry;
};
@ -269,8 +266,8 @@ struct JSAtomState {
};
/* Well-known predefined strings and their atoms. */
extern const char *js_type_str[];
extern const char *js_boolean_str[];
extern const char *js_type_strs[];
extern const char *js_boolean_strs[];
extern const char js_Arguments_str[];
extern const char js_Array_str[];

View File

@ -80,7 +80,7 @@ bool_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
return js_obj_toSource(cx, obj, argc, argv, rval);
JS_snprintf(buf, sizeof buf, "(new %s(%s))",
js_BooleanClass.name,
js_boolean_str[JSVAL_TO_BOOLEAN(v) ? 1 : 0]);
js_boolean_strs[JSVAL_TO_BOOLEAN(v) ? 1 : 0]);
str = JS_NewStringCopyZ(cx, buf);
if (!str)
return JS_FALSE;

View File

@ -163,8 +163,6 @@ js_NewContext(JSRuntime *rt, size_t stackChunkSize)
ok = (rt->atomState.liveAtoms == 0)
? js_InitAtomState(cx, &rt->atomState)
: js_InitPinnedAtoms(cx, &rt->atomState);
if (ok)
ok = js_InitScanner(cx);
if (ok && !rt->scriptFilenameTable)
ok = js_InitRuntimeScriptState(rt);
if (ok)

View File

@ -561,3 +561,8 @@
#error "unknown JS_VERSION"
#endif
/* Features that are present in all versions. */
#define JS_HAS_RESERVED_JAVA_KEYWORDS 1
#define JS_HAS_RESERVED_ECMA_KEYWORDS 1

View File

@ -1670,22 +1670,23 @@ static JSFunctionSpec function_methods[] = {
JSBool
js_IsIdentifier(JSString *str)
{
size_t n;
jschar *s, c;
size_t length;
jschar c, *chars, *end, *s;
n = JSSTRING_LENGTH(str);
if (n == 0)
length = JSSTRING_LENGTH(str);
if (length == 0)
return JS_FALSE;
s = JSSTRING_CHARS(str);
c = *s;
chars = JSSTRING_CHARS(str);
c = *chars;
if (!JS_ISIDSTART(c))
return JS_FALSE;
for (n--; n != 0; n--) {
c = *++s;
end = chars + length;
for (s = chars + 1; s != end; ++s) {
c = *s;
if (!JS_ISIDENT(c))
return JS_FALSE;
}
return JS_TRUE;
return !js_IsKeyword(chars, length);
}
static JSBool

127
js/src/jskeyword.tbl Normal file
View File

@ -0,0 +1,127 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set sw=4 ts=8 et tw=80:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
JS_KEYWORD(break, TOK_BREAK, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(case, TOK_CASE, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(continue, TOK_CONTINUE, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(default, TOK_DEFAULT, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(delete, TOK_DELETE, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(do, TOK_DO, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(else, TOK_ELSE, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(export, TOK_EXPORT, JSOP_NOP, JSVERSION_1_2)
JS_KEYWORD(false, TOK_PRIMARY, JSOP_FALSE, JSVERSION_DEFAULT)
JS_KEYWORD(for, TOK_FOR, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(function, TOK_FUNCTION, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(if, TOK_IF, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(in, TOK_IN, JSOP_IN, JSVERSION_DEFAULT)
JS_KEYWORD(new, TOK_NEW, JSOP_NEW, JSVERSION_DEFAULT)
JS_KEYWORD(null, TOK_PRIMARY, JSOP_NULL, JSVERSION_DEFAULT)
JS_KEYWORD(return, TOK_RETURN, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(switch, TOK_SWITCH, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(this, TOK_PRIMARY, JSOP_THIS, JSVERSION_DEFAULT)
JS_KEYWORD(true, TOK_PRIMARY, JSOP_TRUE, JSVERSION_DEFAULT)
JS_KEYWORD(typeof, TOK_UNARYOP, JSOP_TYPEOF, JSVERSION_DEFAULT)
JS_KEYWORD(var, TOK_VAR, JSOP_DEFVAR, JSVERSION_DEFAULT)
JS_KEYWORD(void, TOK_UNARYOP, JSOP_VOID, JSVERSION_DEFAULT)
JS_KEYWORD(while, TOK_WHILE, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(with, TOK_WITH, JSOP_NOP, JSVERSION_DEFAULT)
#if JS_HAS_CONST
JS_KEYWORD(const, TOK_VAR, JSOP_DEFCONST, JSVERSION_DEFAULT)
#else
JS_KEYWORD(const, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
#endif
#if JS_HAS_EXCEPTIONS
JS_KEYWORD(try, TOK_TRY, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(catch, TOK_CATCH, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(finally, TOK_FINALLY, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(throw, TOK_THROW, JSOP_NOP, JSVERSION_DEFAULT)
#else
JS_KEYWORD(try, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(catch, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(finally, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(throw, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
#endif
#if JS_HAS_INSTANCEOF
JS_KEYWORD(instanceof, TOK_INSTANCEOF, JSOP_INSTANCEOF,JSVERSION_1_4)
#else
JS_KEYWORD(instanceof, TOK_RESERVED, JSOP_NOP, JSVERSION_1_4)
#endif
#if JS_HAS_RESERVED_JAVA_KEYWORDS
JS_KEYWORD(abstract, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(boolean, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(byte, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(char, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(class, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(double, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(extends, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(final, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(float, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(goto, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(implements, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(import, TOK_IMPORT, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(int, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(interface, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(long, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(native, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(package, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(private, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(protected, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(public, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(short, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(static, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(super, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(synchronized,TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(throws, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(transient, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(volatile, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
#endif
#if JS_HAS_RESERVED_ECMA_KEYWORDS
JS_KEYWORD(enum, TOK_RESERVED, JSOP_NOP, JSVERSION_1_3)
#endif
#if JS_HAS_DEBUGGER_KEYWORD
JS_KEYWORD(debugger, TOK_DEBUGGER, JSOP_NOP, JSVERSION_1_3)
#elif JS_HAS_RESERVED_ECMA_KEYWORDS
JS_KEYWORD(debugger, TOK_RESERVED, JSOP_NOP, JSVERSION_1_3)
#endif

460
js/src/jskwgen.c Normal file
View File

@ -0,0 +1,460 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set sw=4 ts=8 et tw=80:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is String Switch Generator for JavaScript Keywords,
* released 2005-12-09.
*
* The Initial Developer of the Original Code is
* Igor Bukanov.
* Portions created by the Initial Developer are Copyright (C) 2005-2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "jsstddef.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
#include "jsconfig.h"
const char * const keyword_list[] = {
#define JS_KEYWORD(keyword, type, op, version) #keyword,
#include "jskeyword.tbl"
#undef JS_KEYWORD
};
struct gen_opt {
FILE *output; /* output file for generated source */
unsigned use_if_threshold; /* max number of choices to generate
"if" selector instead of "switch" */
unsigned char_tail_test_threshold; /* max number of unprocessed columns
to use inlined char compare
for remaining chars and not generic
string compare code */
unsigned indent_level; /* current source identation level */
};
static unsigned column_to_compare;
static int
length_comparator(const void *a, const void *b)
{
const char *str1 = keyword_list[*(unsigned *)a];
const char *str2 = keyword_list[*(unsigned *)b];
return (int)strlen(str1) - (int)strlen(str2);
}
static int
column_comparator(const void *a, const void *b)
{
const char *str1 = keyword_list[*(unsigned *)a];
const char *str2 = keyword_list[*(unsigned *)b];
return (int)str1[column_to_compare] - (int)str2[column_to_compare];
}
static unsigned
count_different_lengths(unsigned indexes[], unsigned nelem)
{
unsigned nlength, current_length, i, l;
current_length = 0;
nlength = 0;
for (i = 0; i != nelem; ++i) {
l = (unsigned)strlen(keyword_list[indexes[i]]);
assert(l != 0);
if (current_length != l) {
++nlength;
current_length = l;
}
}
return nlength;
}
static void
find_char_span_and_count(unsigned indexes[], unsigned nelem, unsigned column,
unsigned *span_result, unsigned *count_result)
{
unsigned i, count;
unsigned char c, prev, minc, maxc;
assert(nelem != 0);
minc = maxc = prev = (unsigned char)keyword_list[indexes[0]][column];
count = 1;
for (i = 1; i != nelem; ++i) {
c = (unsigned char)keyword_list[indexes[i]][column];
if (prev != c) {
prev = c;
++count;
if (minc > c) {
minc = c;
} else if (maxc < c) {
maxc = c;
}
}
}
*span_result = maxc - minc + 1;
*count_result = count;
}
static unsigned
find_optimal_switch_column(struct gen_opt *opt,
unsigned indexes[], unsigned nelem,
unsigned columns[], unsigned unprocessed_columns,
int *use_if_result)
{
unsigned i;
unsigned span, min_span, min_span_index;
unsigned nchar, min_nchar, min_nchar_index;
assert(unprocessed_columns != 0);
i = 0;
min_nchar = min_span = (unsigned)-1;
min_nchar_index = min_span_index = 0;
do {
column_to_compare = columns[i];
qsort(indexes, nelem, sizeof(indexes[0]), column_comparator);
find_char_span_and_count(indexes, nelem, column_to_compare,
&span, &nchar);
assert(span != 0);
if (span == 1) {
assert(nchar == 1);
*use_if_result = 1;
return 1;
}
assert(nchar != 1);
if (min_span > span) {
min_span = span;
min_span_index = i;
}
if (min_nchar > nchar) {
min_nchar = nchar;
min_nchar_index = i;
}
} while (++i != unprocessed_columns);
if (min_nchar <= opt->use_if_threshold) {
*use_if_result = 1;
i = min_nchar_index;
} else {
*use_if_result = 0;
i = min_span_index;
}
/*
* Restore order corresponding to i if it was destroyed by
* subsequent sort.
*/
if (i != unprocessed_columns - 1) {
column_to_compare = columns[i];
qsort(indexes, nelem, sizeof(indexes[0]), column_comparator);
}
return i;
}
static void
p(struct gen_opt *opt, const char *format, ...)
{
va_list ap;
va_start(ap, format);
vfprintf(opt->output, format, ap);
va_end(ap);
}
/* Size for '\xxx' where xxx is octal escape */
#define MIN_QUOTED_CHAR_BUFFER 7
static char *
qchar(char c, char *quoted_buffer)
{
char *s;
s = quoted_buffer;
*s++ = '\'';
switch (c) {
case '\n': c = 'n'; goto one_char_escape;
case '\r': c = 'r'; goto one_char_escape;
case '\t': c = 't'; goto one_char_escape;
case '\f': c = 't'; goto one_char_escape;
case '\0': c = '0'; goto one_char_escape;
case '\'': goto one_char_escape;
one_char_escape:
*s++ = '\\';
break;
default:
if (!isprint(c)) {
*s++ = '\\';
*s++ = (char)('0' + (0x3 & (((unsigned char)c) >> 6)));
*s++ = (char)('0' + (0x7 & (((unsigned char)c) >> 3)));
c = (char)('0' + (0x7 & ((unsigned char)c)));
}
}
*s++ = c;
*s++ = '\'';
*s = '\0';
assert(s + 1 <= quoted_buffer + MIN_QUOTED_CHAR_BUFFER);
return quoted_buffer;
}
static void
nl(struct gen_opt *opt)
{
putc('\n', opt->output);
}
static void
indent(struct gen_opt *opt)
{
unsigned n = opt->indent_level;
while (n != 0) {
--n;
fputs(" ", opt->output);
}
}
static void
line(struct gen_opt *opt, const char *format, ...)
{
va_list ap;
indent(opt);
va_start(ap, format);
vfprintf(opt->output, format, ap);
va_end(ap);
nl(opt);
}
static void
generate_letter_switch_r(struct gen_opt *opt,
unsigned indexes[], unsigned nelem,
unsigned columns[], unsigned unprocessed_columns)
{
char qbuf[MIN_QUOTED_CHAR_BUFFER];
assert(nelem != 0);
if (nelem == 1) {
unsigned kw_index = indexes[0];
const char *keyword = keyword_list[kw_index];
if (unprocessed_columns == 0) {
line(opt, "JSKW_GOT_MATCH(%u) /* %s */", kw_index, keyword);
} else if (unprocessed_columns > opt->char_tail_test_threshold) {
line(opt, "JSKW_TEST_GUESS(%u) /* %s */", kw_index, keyword);
} else {
unsigned i, column;
indent(opt); p(opt, "if (");
for (i = 0; i != unprocessed_columns; ++i) {
column = columns[i];
qchar(keyword[column], qbuf);
p(opt, "%sJSKW_AT(%u)==%s", (i == 0) ? "" : " && ",
column, qbuf);
}
p(opt, ") {"); nl(opt);
++opt->indent_level;
line(opt, "JSKW_GOT_MATCH(%u) /* %s */", kw_index, keyword);
--opt->indent_level;
line(opt, "}");
line(opt, "JSKW_NO_MATCH()");
}
} else {
unsigned optimal_column_index, optimal_column;
unsigned i;
int use_if;
char current;
assert(unprocessed_columns != 0);
optimal_column_index = find_optimal_switch_column(opt, indexes, nelem,
columns,
unprocessed_columns,
&use_if);
optimal_column = columns[optimal_column_index];
columns[optimal_column_index] = columns[unprocessed_columns - 1];
if (!use_if)
line(opt, "switch (JSKW_AT(%u)) {", optimal_column);
current = keyword_list[indexes[0]][optimal_column];
for (i = 0; i != nelem;) {
unsigned same_char_begin = i;
char next = current;
for (++i; i != nelem; ++i) {
next = keyword_list[indexes[i]][optimal_column];
if (next != current)
break;
}
qchar(current, qbuf);
if (use_if) {
line(opt, "if (JSKW_AT(%u) == %s) {", optimal_column, qbuf);
} else {
line(opt, " case %s:", qbuf);
}
++opt->indent_level;
generate_letter_switch_r(opt, indexes + same_char_begin,
i - same_char_begin,
columns, unprocessed_columns - 1);
--opt->indent_level;
if (use_if) {
line(opt, "}");
}
current = next;
}
if (!use_if) {
line(opt, "}");
}
columns[optimal_column_index] = optimal_column;
line(opt, "JSKW_NO_MATCH()");
}
}
static void
generate_letter_switch(struct gen_opt *opt,
unsigned indexes[], unsigned nelem,
unsigned current_length)
{
unsigned *columns;
unsigned i;
columns = malloc(sizeof(columns[0]) * current_length);
if (!columns) {
perror("malloc");
exit(EXIT_FAILURE);
}
for (i = 0; i != current_length; ++i) {
columns[i] = i;
}
generate_letter_switch_r(opt, indexes, nelem, columns, current_length);
free(columns);
}
static void
generate_switch(struct gen_opt *opt)
{
unsigned *indexes;
unsigned nlength;
unsigned i, current;
int use_if;
unsigned nelem;
nelem = sizeof(keyword_list)/sizeof(keyword_list[0]);
line(opt, "/*");
line(opt, " * Generating switch for the list of %u entries:", nelem);
for (i = 0; i != nelem; ++i) {
line(opt, " * %s", keyword_list[i]);
}
line(opt, " */");
indexes = malloc(sizeof(indexes[0]) * nelem);
if (!indexes) {
perror("malloc");
exit(EXIT_FAILURE);
}
for (i = 0; i != nelem; ++i)
indexes[i] = i;
qsort(indexes, nelem, sizeof(indexes[i]), length_comparator);
nlength = count_different_lengths(indexes, nelem);
use_if = (nlength <= opt->use_if_threshold);
if (!use_if)
line(opt, "switch (JSKW_LENGTH()) {");
current = (unsigned)strlen(keyword_list[indexes[0]]);
for (i = 0; i != nelem;) {
unsigned same_length_begin = i;
unsigned next = current;
for (++i; i != nelem; ++i) {
next = (unsigned)strlen(keyword_list[indexes[i]]);
if (next != current)
break;
}
if (use_if) {
line(opt, "if (JSKW_LENGTH() == %u) {", current);
} else {
line(opt, " case %u:", current);
}
++opt->indent_level;
generate_letter_switch(opt, indexes + same_length_begin,
i - same_length_begin,
current);
--opt->indent_level;
if (use_if) {
line(opt, "}");
}
current = next;
}
if (!use_if)
line(opt, "}");
line(opt, "JSKW_NO_MATCH()");
free(indexes);
}
int main(int argc, char **argv)
{
struct gen_opt opt;
if (argc < 2) {
opt.output = stdout;
} else {
opt.output = fopen(argv[1], "w");
if (!opt.output) {
perror("fopen");
exit(EXIT_FAILURE);
}
}
opt.indent_level = 1;
opt.use_if_threshold = 3;
opt.char_tail_test_threshold = 4;
generate_switch(&opt);
if (opt.output != stdout) {
if (fclose(opt.output)) {
perror("fclose");
exit(EXIT_FAILURE);
}
}
return EXIT_SUCCESS;
}

View File

@ -836,12 +836,11 @@ js_obj_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
*rval = STRING_TO_JSVAL(idstr); /* local root */
/*
* If id is a string that's a reserved identifier, or else id is not
* an identifier at all, then it needs to be quoted. Also, negative
* integer ids must be quoted.
* If id is a string that's not an identifier, then it needs to be
* quoted. Also, negative integer ids must be quoted.
*/
if (atom
? (ATOM_KEYWORD(atom) || !js_IsIdentifier(idstr))
? !js_IsIdentifier(idstr)
: (JSID_IS_OBJECT(id) || JSID_TO_INT(id) < 0)) {
idstr = js_QuoteString(cx, idstr, (jschar)'\'');
if (!idstr) {
@ -3421,7 +3420,7 @@ js_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp)
JS_GetStringBytes(str),
(hint == JSTYPE_VOID)
? "primitive type"
: js_type_str[hint]);
: js_type_strs[hint]);
}
return JS_FALSE;
}

View File

@ -70,22 +70,7 @@
#include "jsscript.h"
#include "jsstr.h"
const char js_const_str[] = "const";
const char js_var_str[] = "var";
const char js_function_str[] = "function";
const char js_in_str[] = "in";
const char js_instanceof_str[] = "instanceof";
const char js_new_str[] = "new";
const char js_delete_str[] = "delete";
const char js_typeof_str[] = "typeof";
const char js_void_str[] = "void";
const char js_null_str[] = "null";
const char js_this_str[] = "this";
const char js_false_str[] = "false";
const char js_true_str[] = "true";
const char js_default_str[] = "default";
const char *js_incop_str[] = {"++", "--"};
static const char js_incop_strs[][3] = {"++", "--"};
/* Pollute the namespace locally for MSVC Win16, but not for WatCom. */
#ifdef __WINDOWS_386__
@ -914,8 +899,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
* Callers know that ATOM_IS_STRING(atom), and we leave it to the optimizer to
* common ATOM_TO_STRING(atom) here and near the call sites.
*/
#define ATOM_IS_IDENTIFIER(atom) \
(!ATOM_KEYWORD(atom) && js_IsIdentifier(ATOM_TO_STRING(atom)))
#define ATOM_IS_IDENTIFIER(atom) js_IsIdentifier(ATOM_TO_STRING(atom))
/*
* Given an atom already fetched from jp->script's atom map, quote/escape its
@ -1846,7 +1830,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
return JS_FALSE;
RETRACT(&ss->sprinter, lval);
todo = Sprint(&ss->sprinter, "%s%s",
js_incop_str[!(cs->format & JOF_INC)], lval);
js_incop_strs[!(cs->format & JOF_INC)], lval);
break;
case JSOP_INCPROP:
@ -1854,7 +1838,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
GET_ATOM_QUOTE_AND_FMT("%s%s[%s]", "%s%s.%s", rval);
lval = POP_STR();
todo = Sprint(&ss->sprinter, fmt,
js_incop_str[!(cs->format & JOF_INC)],
js_incop_strs[!(cs->format & JOF_INC)],
lval, rval);
break;
@ -1867,11 +1851,11 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
(js_CodeSpec[lastop].format & JOF_XMLNAME)
? "%s%s.%s"
: "%s%s[%s]",
js_incop_str[!(cs->format & JOF_INC)],
js_incop_strs[!(cs->format & JOF_INC)],
lval, xval);
} else {
todo = Sprint(&ss->sprinter, "%s%s",
js_incop_str[!(cs->format & JOF_INC)], lval);
js_incop_strs[!(cs->format & JOF_INC)], lval);
}
break;
@ -1898,7 +1882,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
return JS_FALSE;
todo = STR2OFF(&ss->sprinter, lval);
SprintPut(&ss->sprinter,
js_incop_str[!(cs->format & JOF_INC)],
js_incop_strs[!(cs->format & JOF_INC)],
2);
break;
@ -1907,7 +1891,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
GET_ATOM_QUOTE_AND_FMT("%s[%s]%s", "%s.%s%s", rval);
lval = POP_STR();
todo = Sprint(&ss->sprinter, fmt, lval, rval,
js_incop_str[!(cs->format & JOF_INC)]);
js_incop_strs[!(cs->format & JOF_INC)]);
break;
case JSOP_ELEMINC:
@ -1920,10 +1904,10 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
? "%s.%s%s"
: "%s[%s]%s",
lval, xval,
js_incop_str[!(cs->format & JOF_INC)]);
js_incop_strs[!(cs->format & JOF_INC)]);
} else {
todo = Sprint(&ss->sprinter, "%s%s",
lval, js_incop_str[!(cs->format & JOF_INC)]);
lval, js_incop_strs[!(cs->format & JOF_INC)]);
}
break;

View File

@ -74,133 +74,80 @@
#include "jsxml.h"
#endif
#define RESERVE_JAVA_KEYWORDS
#define RESERVE_ECMA_KEYWORDS
#define MAX_KEYWORD_LENGTH 12
static struct keyword {
const char *name;
#define JS_KEYWORD(keyword, type, op, version) \
const char js_##keyword##_str[] = #keyword;
#include "jskeyword.tbl"
#undef JS_KEYWORD
struct keyword {
const char *chars; /* C string with keyword text */
JSTokenType tokentype; /* JSTokenType */
JSOp op; /* JSOp */
JSVersion version; /* JSVersion */
} keywords[] = {
{"break", TOK_BREAK, JSOP_NOP, JSVERSION_DEFAULT},
{"case", TOK_CASE, JSOP_NOP, JSVERSION_DEFAULT},
{"continue", TOK_CONTINUE, JSOP_NOP, JSVERSION_DEFAULT},
{js_default_str, TOK_DEFAULT, JSOP_NOP, JSVERSION_DEFAULT},
{js_delete_str, TOK_DELETE, JSOP_NOP, JSVERSION_DEFAULT},
{"do", TOK_DO, JSOP_NOP, JSVERSION_DEFAULT},
{"else", TOK_ELSE, JSOP_NOP, JSVERSION_DEFAULT},
{"export", TOK_EXPORT, JSOP_NOP, JSVERSION_1_2},
{js_false_str, TOK_PRIMARY, JSOP_FALSE, JSVERSION_DEFAULT},
{"for", TOK_FOR, JSOP_NOP, JSVERSION_DEFAULT},
{js_function_str, TOK_FUNCTION, JSOP_NOP, JSVERSION_DEFAULT},
{"if", TOK_IF, JSOP_NOP, JSVERSION_DEFAULT},
{js_in_str, TOK_IN, JSOP_IN, JSVERSION_DEFAULT},
{js_new_str, TOK_NEW, JSOP_NEW, JSVERSION_DEFAULT},
{js_null_str, TOK_PRIMARY, JSOP_NULL, JSVERSION_DEFAULT},
{"return", TOK_RETURN, JSOP_NOP, JSVERSION_DEFAULT},
{"switch", TOK_SWITCH, JSOP_NOP, JSVERSION_DEFAULT},
{js_this_str, TOK_PRIMARY, JSOP_THIS, JSVERSION_DEFAULT},
{js_true_str, TOK_PRIMARY, JSOP_TRUE, JSVERSION_DEFAULT},
{js_typeof_str, TOK_UNARYOP, JSOP_TYPEOF,JSVERSION_DEFAULT},
{js_var_str, TOK_VAR, JSOP_DEFVAR,JSVERSION_DEFAULT},
{js_void_str, TOK_UNARYOP, JSOP_VOID, JSVERSION_DEFAULT},
{"while", TOK_WHILE, JSOP_NOP, JSVERSION_DEFAULT},
{"with", TOK_WITH, JSOP_NOP, JSVERSION_DEFAULT},
#if JS_HAS_CONST
{js_const_str, TOK_VAR, JSOP_DEFCONST,JSVERSION_DEFAULT},
#else
{js_const_str, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT},
#endif
#if JS_HAS_EXCEPTIONS
{"try", TOK_TRY, JSOP_NOP, JSVERSION_DEFAULT},
{"catch", TOK_CATCH, JSOP_NOP, JSVERSION_DEFAULT},
{"finally", TOK_FINALLY, JSOP_NOP, JSVERSION_DEFAULT},
{"throw", TOK_THROW, JSOP_NOP, JSVERSION_DEFAULT},
#else
{"try", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT},
{"catch", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT},
{"finally", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT},
{"throw", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT},
#endif
#if JS_HAS_INSTANCEOF
{js_instanceof_str, TOK_INSTANCEOF, JSOP_INSTANCEOF,JSVERSION_1_4},
#else
{js_instanceof_str, TOK_RESERVED, JSOP_NOP, JSVERSION_1_4},
#endif
#ifdef RESERVE_JAVA_KEYWORDS
{"abstract", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT},
{"boolean", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT},
{"byte", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT},
{"char", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT},
{"class", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT},
{"double", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT},
{"extends", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT},
{"final", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT},
{"float", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT},
{"goto", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT},
{"implements", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT},
{"import", TOK_IMPORT, JSOP_NOP, JSVERSION_DEFAULT},
{"int", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT},
{"interface", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT},
{"long", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT},
{"native", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT},
{"package", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT},
{"private", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT},
{"protected", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT},
{"public", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT},
{"short", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT},
{"static", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT},
{"super", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT},
{"synchronized", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT},
{"throws", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT},
{"transient", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT},
{"volatile", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT},
#endif
#ifdef RESERVE_ECMA_KEYWORDS
{"enum", TOK_RESERVED, JSOP_NOP, JSVERSION_1_3},
#endif
#if JS_HAS_DEBUGGER_KEYWORD
{"debugger", TOK_DEBUGGER, JSOP_NOP, JSVERSION_1_3},
#elif defined(RESERVE_ECMA_KEYWORDS)
{"debugger", TOK_RESERVED, JSOP_NOP, JSVERSION_1_3},
#endif
{0, TOK_EOF, JSOP_NOP, JSVERSION_DEFAULT}
};
JSBool
js_InitScanner(JSContext *cx)
{
struct keyword *kw;
size_t length;
JSAtom *atom;
static const struct keyword keyword_defs[] = {
#define JS_KEYWORD(keyword, type, op, version) \
{js_##keyword##_str, type, op, version},
#include "jskeyword.tbl"
#undef JS_KEYWORD
};
for (kw = keywords; kw->name; kw++) {
length = strlen(kw->name);
JS_ASSERT(length <= MAX_KEYWORD_LENGTH);
atom = js_Atomize(cx, kw->name, length, ATOM_PINNED);
if (!atom)
return JS_FALSE;
ATOM_SET_KEYWORD(atom, kw);
}
return JS_TRUE;
#define KEYWORD_COUNT (sizeof keyword_defs / sizeof keyword_defs[0])
static const struct keyword *
FindKeyword(const jschar *s, size_t length)
{
register size_t i;
const struct keyword *kw;
const char *chars;
JS_ASSERT(length != 0);
#define JSKW_LENGTH() length
#define JSKW_AT(column) s[column]
#define JSKW_GOT_MATCH(index) i = (index); goto got_match;
#define JSKW_TEST_GUESS(index) i = (index); goto test_guess;
#define JSKW_NO_MATCH() goto no_match;
#include "jsautokw.h"
#undef JSKW_NO_MATCH
#undef JSKW_TEST_GUESS
#undef JSKW_GOT_MATCH
#undef JSKW_AT
#undef JSKW_LENGTH
got_match:
return &keyword_defs[i];
test_guess:
kw = &keyword_defs[i];
chars = kw->chars;
do {
if (*s++ != (unsigned char)(*chars++))
goto no_match;
} while (--length != 0);
return kw;
no_match:
return NULL;
}
JSBool
js_IsKeyword(const jschar *str, size_t length)
{
JS_ASSERT(length != 0);
return FindKeyword(str, length) != NULL;
}
JS_FRIEND_API(void)
js_MapKeywords(void (*mapfun)(const char *))
{
struct keyword *kw;
size_t i;
for (kw = keywords; kw->name; kw++)
mapfun(kw->name);
for (i = 0; i != KEYWORD_COUNT; ++i)
mapfun(keyword_defs[i].chars);
}
JSTokenStream *
@ -755,7 +702,7 @@ js_ReportCompileErrorNumber(JSContext *cx, void *handle, uintN flags,
&report, JS_TRUE, ap);
va_end(ap);
/*
/*
* We have to do this here because js_ReportCompileErrorNumberUC doesn't
* need to do this.
*/
@ -779,7 +726,7 @@ js_ReportCompileErrorNumberUC(JSContext *cx, void *handle, uintN flags,
if ((flags & JSREPORT_STRICT) && !JS_HAS_STRICT_OPTION(cx))
return JS_TRUE;
va_start(ap, errorNumber);
warning = ReportCompileErrorNumber(cx, handle, flags, errorNumber,
&report, JS_FALSE, ap);
@ -1114,6 +1061,7 @@ js_GetToken(JSContext *cx, JSTokenStream *ts)
JSToken *tp;
JSAtom *atom;
JSBool hadUnicodeEscape;
const struct keyword *kw;
#define INIT_TOKENBUF() (ts->tokenbuf.ptr = ts->tokenbuf.base)
#define NUL_TERM_TOKENBUF() (*ts->tokenbuf.ptr = 0)
@ -1335,14 +1283,8 @@ retry:
}
UngetChar(ts, c);
atom = TOKENBUF_TO_ATOM();
if (!atom)
goto error;
if (!hadUnicodeEscape && ATOM_KEYWORD(atom)) {
struct keyword *kw;
JS_ASSERT(!(atom->flags & ATOM_HIDDEN));
kw = ATOM_KEYWORD(atom);
if (!hadUnicodeEscape &&
(kw = FindKeyword(TOKENBUF_BASE(), TOKENBUF_LENGTH()))) {
if (kw->tokentype == TOK_RESERVED) {
char buf[MAX_KEYWORD_LENGTH + 1];
size_t buflen = sizeof(buf) - 1;
@ -1364,6 +1306,10 @@ retry:
goto out;
}
}
atom = TOKENBUF_TO_ATOM();
if (!atom)
goto error;
tp->t_op = JSOP_NAME;
tp->t_atom = atom;
tt = TOK_NAME;

View File

@ -301,10 +301,10 @@ extern JS_FRIEND_API(int)
js_fgets(char *buf, int size, FILE *file);
/*
* Initialize the scanner, installing JS keywords into cx's global scope.
* Return true if the given char array forms JavaScript keyword.
*/
extern JSBool
js_InitScanner(JSContext *cx);
js_IsKeyword(const jschar *str, size_t length);
/*
* Friend-exported API entry point to call a mapping function on each reserved

View File

@ -2402,7 +2402,7 @@ GetNamespace(JSContext *cx, JSXMLQName *qn, const JSXMLArray *inScopeNSes)
qn->prefix
? js_ValueToPrintableString(cx,
STRING_TO_JSVAL(qn->prefix))
: js_type_str[JSTYPE_VOID]);
: js_type_strs[JSTYPE_VOID]);
return NULL;
}
@ -2906,9 +2906,9 @@ ToXMLString(JSContext *cx, jsval v)
if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v)) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_BAD_XML_CONVERSION,
js_type_str[JSVAL_IS_NULL(v)
? JSTYPE_NULL
: JSTYPE_VOID]);
js_type_strs[JSVAL_IS_NULL(v)
? JSTYPE_NULL
: JSTYPE_VOID]);
return NULL;
}

View File

@ -177,7 +177,7 @@ endif
+$(LOOP_OVER_DIRS)
clean:
rm -rf $(OBJS)
rm -rf $(OBJS) $(GARBAGE)
@cd fdlibm; $(MAKE) -f Makefile.ref clean
clobber: