Back to index

lightning-sunbird  0.9+nobinonly
Classes | Defines | Typedefs | Enumerations | Functions | Variables
jsscan.h File Reference
#include <stddef.h>
#include <stdio.h>
#include "jsconfig.h"
#include "jsopcode.h"
#include "jsprvtd.h"
#include "jspubtd.h"
#include "jskeyword.tbl"
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  JSStringBuffer
struct  JSTokenPtr
struct  JSTokenPos
struct  JSToken
struct  JSTokenBuf
struct  JSTokenStream
union  JSToken.u
struct  JSToken.u.s
struct  JSToken.u.p

Defines

#define JS_KEYWORD(keyword, type, op, version)   extern const char js_##keyword##_str[];
#define IS_PRIMARY_TOKEN(tt)   ((uintN)((tt) - TOK_NAME) <= (uintN)(TOK_PRIMARY - TOK_NAME))
#define TOKEN_TYPE_IS_XML(tt)   (tt == TOK_AT || tt == TOK_DBLCOLON || tt == TOK_ANYNAME)
#define TOKEN_TYPE_IS_DECL(tt)   ((tt) == TOK_VAR || (tt) == TOK_LET)
#define STRING_BUFFER_ERROR_BASE   ((jschar *) 1)
#define STRING_BUFFER_OK(sb)   ((sb)->base != STRING_BUFFER_ERROR_BASE)
#define STRING_BUFFER_OFFSET(sb)   ((sb)->ptr -(sb)->base)
#define t_op   u.s.op
#define t_atom   u.s.atom
#define t_atom2   u.p.atom2
#define t_dval   u.dval
#define JS_LINE_LIMIT
#define NTOKENS   4 /* 1 current + 2 lookahead, rounded */
#define NTOKENS_MASK   (NTOKENS-1) /* to power of 2 to avoid divmod by 3 */
#define CURRENT_TOKEN(ts)   ((ts)->tokens[(ts)->cursor])
#define ON_CURRENT_LINE(ts, pos)   ((uint16)(ts)->lineno == (pos).end.lineno)
#define TSF_ERROR   0x01 /* fatal error while compiling */
#define TSF_EOF   0x02 /* hit end of file */
#define TSF_NEWLINES   0x04 /* tokenize newlines */
#define TSF_OPERAND   0x08 /* looking for operand, not operator */
#define TSF_NLFLAG   0x20 /* last linebuf ended with \n */
#define TSF_CRFLAG   0x40 /* linebuf would have ended with \r */
#define TSF_DIRTYLINE   0x80 /* non-whitespace since start of line */
#define TSF_OWNFILENAME   0x100 /* ts->filename is malloc'd */
#define TSF_XMLTAGMODE   0x200 /* scanning within an XML tag in E4X */
#define TSF_XMLTEXTMODE   0x400 /* scanning XMLText terminal from E4X */
#define TSF_XMLONLYMODE   0x800 /* don't scan {expr} within text/tag */
#define TSF_UNEXPECTED_EOF   0x1000
#define TSF_IN_HTML_COMMENT   0x2000
#define TSF_KEYWORD_IS_NAME   0x4000
#define LINE_SEPARATOR   0x2028
#define PARA_SEPARATOR   0x2029
#define js_IsKeyword(chars, length)   (js_CheckKeyword(chars, length) != TOK_EOF)
#define JSREPORT_HANDLE   0x300
#define JSREPORT_TS   0x000
#define JSREPORT_CG   0x100
#define JSREPORT_PN   0x200

Typedefs

typedef enum JSTokenType JSTokenType
typedef struct JSTokenBuf JSTokenBuf

Enumerations

enum  JSTokenType {
  TOK_ERROR = -1, TOK_EOF = 0, TOK_EOL = 1, TOK_SEMI = 2,
  TOK_COMMA = 3, TOK_ASSIGN = 4, TOK_HOOK = 5, TOK_COLON = 6,
  TOK_OR = 7, TOK_AND = 8, TOK_BITOR = 9, TOK_BITXOR = 10,
  TOK_BITAND = 11, TOK_EQOP = 12, TOK_RELOP = 13, TOK_SHOP = 14,
  TOK_PLUS = 15, TOK_MINUS = 16, TOK_STAR = 17, TOK_DIVOP = 18,
  TOK_UNARYOP = 19, TOK_INC = 20, TOK_DEC = 21, TOK_DOT = 22,
  TOK_LB = 23, TOK_RB = 24, TOK_LC = 25, TOK_RC = 26,
  TOK_LP = 27, TOK_RP = 28, TOK_NAME = 29, TOK_NUMBER = 30,
  TOK_STRING = 31, TOK_OBJECT = 32, TOK_PRIMARY = 33, TOK_FUNCTION = 34,
  TOK_EXPORT = 35, TOK_IMPORT = 36, TOK_IF = 37, TOK_ELSE = 38,
  TOK_SWITCH = 39, TOK_CASE = 40, TOK_DEFAULT = 41, TOK_WHILE = 42,
  TOK_DO = 43, TOK_FOR = 44, TOK_BREAK = 45, TOK_CONTINUE = 46,
  TOK_IN = 47, TOK_VAR = 48, TOK_WITH = 49, TOK_RETURN = 50,
  TOK_NEW = 51, TOK_DELETE = 52, TOK_DEFSHARP = 53, TOK_USESHARP = 54,
  TOK_TRY = 55, TOK_CATCH = 56, TOK_FINALLY = 57, TOK_THROW = 58,
  TOK_INSTANCEOF = 59, TOK_DEBUGGER = 60, TOK_XMLSTAGO = 61, TOK_XMLETAGO = 62,
  TOK_XMLPTAGC = 63, TOK_XMLTAGC = 64, TOK_XMLNAME = 65, TOK_XMLATTR = 66,
  TOK_XMLSPACE = 67, TOK_XMLTEXT = 68, TOK_XMLCOMMENT = 69, TOK_XMLCDATA = 70,
  TOK_XMLPI = 71, TOK_AT = 72, TOK_DBLCOLON = 73, TOK_ANYNAME = 74,
  TOK_DBLDOT = 75, TOK_FILTER = 76, TOK_XMLELEM = 77, TOK_XMLLIST = 78,
  TOK_YIELD = 79, TOK_ARRAYCOMP = 80, TOK_ARRAYPUSH = 81, TOK_LEXICALSCOPE = 82,
  TOK_LET = 83, TOK_BODY = 84, TOK_RESERVED, TOK_LIMIT
}

Functions

void js_InitStringBuffer (JSStringBuffer *sb)
void js_FinishStringBuffer (JSStringBuffer *sb)
void js_AppendChar (JSStringBuffer *sb, jschar c)
void js_RepeatChar (JSStringBuffer *sb, jschar c, uintN count)
void js_AppendCString (JSStringBuffer *sb, const char *asciiz)
void js_AppendJSString (JSStringBuffer *sb, JSString *str)
JSTokenStreamjs_NewTokenStream (JSContext *cx, const jschar *base, size_t length, const char *filename, uintN lineno, JSPrincipals *principals)
 JS_FRIEND_API (JSTokenStream *) js_NewBufferTokenStream(JSContext *cx
 JS_FRIEND_API (JSBool) js_CloseTokenStream(JSContext *cx
 JS_FRIEND_API (int) js_fgets(char *buf
JSTokenType js_CheckKeyword (const jschar *chars, size_t length)
 JS_FRIEND_API (void) js_MapKeywords(void(*mapfun)(const char *))
JSBool js_ReportCompileErrorNumber (JSContext *cx, void *handle, uintN flags, uintN errorNumber,...)
JSBool js_ReportCompileErrorNumberUC (JSContext *cx, void *handle, uintN flags, uintN errorNumber,...)
JSTokenType js_PeekToken (JSContext *cx, JSTokenStream *ts)
JSTokenType js_PeekTokenSameLine (JSContext *cx, JSTokenStream *ts)
JSTokenType js_GetToken (JSContext *cx, JSTokenStream *ts)
void js_UngetToken (JSTokenStream *ts)
JSBool js_MatchToken (JSContext *cx, JSTokenStream *ts, JSTokenType tt)

Variables

const jscharbase
const jschar size_t length
const char * filename
const char FILEdefaultfp
JSTokenStreamts
int size
int FILEfile

Class Documentation

struct JSTokenPtr

Definition at line 188 of file jsscan.h.

Class Members
uint16 index
uint16 lineno
struct JSTokenPos

Definition at line 193 of file jsscan.h.

Class Members
JSTokenPtr begin
JSTokenPtr end
struct JSToken

Definition at line 198 of file jsscan.h.

Class Members
JSTokenPos pos
jschar * ptr
JSTokenType type
union JSToken u
struct JSTokenBuf

Definition at line 220 of file jsscan.h.

Class Members
jschar * base
jschar * limit
jschar * ptr
struct JSTokenStream

Definition at line 230 of file jsscan.h.

Collaboration diagram for JSTokenStream:
Class Members
uintN cursor
FILE * file
const char * filename
uintN flags
JSTokenBuf linebuf
ptrdiff_t linelen
uintN lineno
ptrdiff_t linepos
JSSourceHandler listener
void * listenerData
void * listenerTSData
uintN lookahead
JSPrincipals * principals
jschar * saveEOL
JSStringBuffer tokenbuf
JSToken tokens
jschar ungetbuf
uintN ungetpos
JSTokenBuf userbuf
union JSToken.u

Definition at line 202 of file jsscan.h.

Class Members
jsdouble dval
u p
u s
struct JSToken.u.s

Definition at line 203 of file jsscan.h.

Class Members
JSAtom * atom
JSOp op
struct JSToken.u.p

Definition at line 207 of file jsscan.h.

Class Members
JSAtom * atom
JSAtom * atom2

Define Documentation

#define CURRENT_TOKEN (   ts)    ((ts)->tokens[(ts)->cursor])

Definition at line 253 of file jsscan.h.

Definition at line 145 of file jsscan.h.

Definition at line 331 of file jsscan.h.

#define JS_KEYWORD (   keyword,
  type,
  op,
  version 
)    extern const char js_##keyword##_str[];

Definition at line 54 of file jsscan.h.

Value:
256             /* logical line buffer size limit --
                                           physical line length is unlimited */

Definition at line 226 of file jsscan.h.

#define JSREPORT_CG   0x100

Definition at line 356 of file jsscan.h.

#define JSREPORT_HANDLE   0x300

Definition at line 354 of file jsscan.h.

#define JSREPORT_PN   0x200

Definition at line 357 of file jsscan.h.

#define JSREPORT_TS   0x000

Definition at line 355 of file jsscan.h.

#define LINE_SEPARATOR   0x2028

Definition at line 297 of file jsscan.h.

#define NTOKENS   4 /* 1 current + 2 lookahead, rounded */

Definition at line 227 of file jsscan.h.

#define NTOKENS_MASK   (NTOKENS-1) /* to power of 2 to avoid divmod by 3 */

Definition at line 228 of file jsscan.h.

#define ON_CURRENT_LINE (   ts,
  pos 
)    ((uint16)(ts)->lineno == (pos).end.lineno)

Definition at line 254 of file jsscan.h.

#define PARA_SEPARATOR   0x2029

Definition at line 298 of file jsscan.h.

Definition at line 166 of file jsscan.h.

#define STRING_BUFFER_OFFSET (   sb)    ((sb)->ptr -(sb)->base)

Definition at line 168 of file jsscan.h.

Definition at line 167 of file jsscan.h.

Definition at line 216 of file jsscan.h.

#define t_atom2   u.p.atom2

Definition at line 217 of file jsscan.h.

Definition at line 218 of file jsscan.h.

Definition at line 215 of file jsscan.h.

#define TOKEN_TYPE_IS_DECL (   tt)    ((tt) == TOK_VAR || (tt) == TOK_LET)

Definition at line 152 of file jsscan.h.

#define TOKEN_TYPE_IS_XML (   tt)    (tt == TOK_AT || tt == TOK_DBLCOLON || tt == TOK_ANYNAME)

Definition at line 148 of file jsscan.h.

#define TSF_CRFLAG   0x40 /* linebuf would have ended with \r */

Definition at line 262 of file jsscan.h.

#define TSF_DIRTYLINE   0x80 /* non-whitespace since start of line */

Definition at line 263 of file jsscan.h.

#define TSF_EOF   0x02 /* hit end of file */

Definition at line 258 of file jsscan.h.

#define TSF_ERROR   0x01 /* fatal error while compiling */

Definition at line 257 of file jsscan.h.

Definition at line 291 of file jsscan.h.

Definition at line 294 of file jsscan.h.

#define TSF_NEWLINES   0x04 /* tokenize newlines */

Definition at line 259 of file jsscan.h.

#define TSF_NLFLAG   0x20 /* last linebuf ended with \n */

Definition at line 261 of file jsscan.h.

#define TSF_OPERAND   0x08 /* looking for operand, not operator */

Definition at line 260 of file jsscan.h.

#define TSF_OWNFILENAME   0x100 /* ts->filename is malloc'd */

Definition at line 264 of file jsscan.h.

#define TSF_UNEXPECTED_EOF   0x1000

Definition at line 270 of file jsscan.h.

#define TSF_XMLONLYMODE   0x800 /* don't scan {expr} within text/tag */

Definition at line 267 of file jsscan.h.

#define TSF_XMLTAGMODE   0x200 /* scanning within an XML tag in E4X */

Definition at line 265 of file jsscan.h.

#define TSF_XMLTEXTMODE   0x400 /* scanning XMLText terminal from E4X */

Definition at line 266 of file jsscan.h.


Typedef Documentation

typedef struct JSTokenBuf JSTokenBuf
typedef enum JSTokenType JSTokenType

Enumeration Type Documentation

Enumerator:
TOK_ERROR 
TOK_EOF 
TOK_EOL 
TOK_SEMI 
TOK_COMMA 
TOK_ASSIGN 
TOK_HOOK 
TOK_COLON 
TOK_OR 
TOK_AND 
TOK_BITOR 
TOK_BITXOR 
TOK_BITAND 
TOK_EQOP 
TOK_RELOP 
TOK_SHOP 
TOK_PLUS 
TOK_MINUS 
TOK_STAR 
TOK_DIVOP 
TOK_UNARYOP 
TOK_INC 
TOK_DEC 
TOK_DOT 
TOK_LB 
TOK_RB 
TOK_LC 
TOK_RC 
TOK_LP 
TOK_RP 
TOK_NAME 
TOK_NUMBER 
TOK_STRING 
TOK_OBJECT 
TOK_PRIMARY 
TOK_FUNCTION 
TOK_EXPORT 
TOK_IMPORT 
TOK_IF 
TOK_ELSE 
TOK_SWITCH 
TOK_CASE 
TOK_DEFAULT 
TOK_WHILE 
TOK_DO 
TOK_FOR 
TOK_BREAK 
TOK_CONTINUE 
TOK_IN 
TOK_VAR 
TOK_WITH 
TOK_RETURN 
TOK_NEW 
TOK_DELETE 
TOK_DEFSHARP 
TOK_USESHARP 
TOK_TRY 
TOK_CATCH 
TOK_FINALLY 
TOK_THROW 
TOK_INSTANCEOF 
TOK_DEBUGGER 
TOK_XMLSTAGO 
TOK_XMLETAGO 
TOK_XMLPTAGC 
TOK_XMLTAGC 
TOK_XMLNAME 
TOK_XMLATTR 
TOK_XMLSPACE 
TOK_XMLTEXT 
TOK_XMLCOMMENT 
TOK_XMLCDATA 
TOK_XMLPI 
TOK_AT 
TOK_DBLCOLON 
TOK_ANYNAME 
TOK_DBLDOT 
TOK_FILTER 
TOK_XMLELEM 
TOK_XMLLIST 
TOK_YIELD 
TOK_ARRAYCOMP 
TOK_ARRAYPUSH 
TOK_LEXICALSCOPE 
TOK_LET 
TOK_BODY 
TOK_RESERVED 
TOK_LIMIT 

Definition at line 59 of file jsscan.h.

                         {
    TOK_ERROR = -1,                     /* well-known as the only code < EOF */
    TOK_EOF = 0,                        /* end of file */
    TOK_EOL = 1,                        /* end of line */
    TOK_SEMI = 2,                       /* semicolon */
    TOK_COMMA = 3,                      /* comma operator */
    TOK_ASSIGN = 4,                     /* assignment ops (= += -= etc.) */
    TOK_HOOK = 5, TOK_COLON = 6,        /* conditional (?:) */
    TOK_OR = 7,                         /* logical or (||) */
    TOK_AND = 8,                        /* logical and (&&) */
    TOK_BITOR = 9,                      /* bitwise-or (|) */
    TOK_BITXOR = 10,                    /* bitwise-xor (^) */
    TOK_BITAND = 11,                    /* bitwise-and (&) */
    TOK_EQOP = 12,                      /* equality ops (== !=) */
    TOK_RELOP = 13,                     /* relational ops (< <= > >=) */
    TOK_SHOP = 14,                      /* shift ops (<< >> >>>) */
    TOK_PLUS = 15,                      /* plus */
    TOK_MINUS = 16,                     /* minus */
    TOK_STAR = 17, TOK_DIVOP = 18,      /* multiply/divide ops (* / %) */
    TOK_UNARYOP = 19,                   /* unary prefix operator */
    TOK_INC = 20, TOK_DEC = 21,         /* increment/decrement (++ --) */
    TOK_DOT = 22,                       /* member operator (.) */
    TOK_LB = 23, TOK_RB = 24,           /* left and right brackets */
    TOK_LC = 25, TOK_RC = 26,           /* left and right curlies (braces) */
    TOK_LP = 27, TOK_RP = 28,           /* left and right parentheses */
    TOK_NAME = 29,                      /* identifier */
    TOK_NUMBER = 30,                    /* numeric constant */
    TOK_STRING = 31,                    /* string constant */
    TOK_OBJECT = 32,                    /* RegExp or other object constant */
    TOK_PRIMARY = 33,                   /* true, false, null, this, super */
    TOK_FUNCTION = 34,                  /* function keyword */
    TOK_EXPORT = 35,                    /* export keyword */
    TOK_IMPORT = 36,                    /* import keyword */
    TOK_IF = 37,                        /* if keyword */
    TOK_ELSE = 38,                      /* else keyword */
    TOK_SWITCH = 39,                    /* switch keyword */
    TOK_CASE = 40,                      /* case keyword */
    TOK_DEFAULT = 41,                   /* default keyword */
    TOK_WHILE = 42,                     /* while keyword */
    TOK_DO = 43,                        /* do keyword */
    TOK_FOR = 44,                       /* for keyword */
    TOK_BREAK = 45,                     /* break keyword */
    TOK_CONTINUE = 46,                  /* continue keyword */
    TOK_IN = 47,                        /* in keyword */
    TOK_VAR = 48,                       /* var keyword */
    TOK_WITH = 49,                      /* with keyword */
    TOK_RETURN = 50,                    /* return keyword */
    TOK_NEW = 51,                       /* new keyword */
    TOK_DELETE = 52,                    /* delete keyword */
    TOK_DEFSHARP = 53,                  /* #n= for object/array initializers */
    TOK_USESHARP = 54,                  /* #n# for object/array initializers */
    TOK_TRY = 55,                       /* try keyword */
    TOK_CATCH = 56,                     /* catch keyword */
    TOK_FINALLY = 57,                   /* finally keyword */
    TOK_THROW = 58,                     /* throw keyword */
    TOK_INSTANCEOF = 59,                /* instanceof keyword */
    TOK_DEBUGGER = 60,                  /* debugger keyword */
    TOK_XMLSTAGO = 61,                  /* XML start tag open (<) */
    TOK_XMLETAGO = 62,                  /* XML end tag open (</) */
    TOK_XMLPTAGC = 63,                  /* XML point tag close (/>) */
    TOK_XMLTAGC = 64,                   /* XML start or end tag close (>) */
    TOK_XMLNAME = 65,                   /* XML start-tag non-final fragment */
    TOK_XMLATTR = 66,                   /* XML quoted attribute value */
    TOK_XMLSPACE = 67,                  /* XML whitespace */
    TOK_XMLTEXT = 68,                   /* XML text */
    TOK_XMLCOMMENT = 69,                /* XML comment */
    TOK_XMLCDATA = 70,                  /* XML CDATA section */
    TOK_XMLPI = 71,                     /* XML processing instruction */
    TOK_AT = 72,                        /* XML attribute op (@) */
    TOK_DBLCOLON = 73,                  /* namespace qualified name op (::) */
    TOK_ANYNAME = 74,                   /* XML AnyName singleton (*) */
    TOK_DBLDOT = 75,                    /* XML descendant op (..) */
    TOK_FILTER = 76,                    /* XML filtering predicate op (.()) */
    TOK_XMLELEM = 77,                   /* XML element node type (no token) */
    TOK_XMLLIST = 78,                   /* XML list node type (no token) */
    TOK_YIELD = 79,                     /* yield from generator function */
    TOK_ARRAYCOMP = 80,                 /* array comprehension initialiser */
    TOK_ARRAYPUSH = 81,                 /* array push within comprehension */
    TOK_LEXICALSCOPE = 82,              /* block scope AST node label */
    TOK_LET = 83,                       /* let keyword */
    TOK_BODY = 84,                      /* synthetic body of function with
                                           destructuring formal parameters */
    TOK_RESERVED,                       /* reserved keywords */
    TOK_LIMIT                           /* domain size */
} JSTokenType;

Function Documentation

Definition at line 819 of file jsscan.c.

{
    jschar *bp;

    if (!STRING_BUFFER_OK(sb))
        return;
    if (!ENSURE_STRING_BUFFER(sb, 1))
        return;
    bp = sb->ptr;
    *bp++ = c;
    *bp = 0;
    sb->ptr = bp;
}

Here is the caller graph for this function:

void js_AppendCString ( JSStringBuffer sb,
const char *  asciiz 
)

Definition at line 851 of file jsscan.c.

{
    size_t length;
    jschar *bp;

    if (!STRING_BUFFER_OK(sb) || *asciiz == '\0')
        return;
    length = strlen(asciiz);
    if (!ENSURE_STRING_BUFFER(sb, length))
        return;
    for (bp = sb->ptr; length; --length)
        *bp++ = (jschar) *asciiz++;
    *bp = 0;
    sb->ptr = bp;
}

Here is the caller graph for this function:

Definition at line 868 of file jsscan.c.

{
    size_t length;
    jschar *bp;

    if (!STRING_BUFFER_OK(sb))
        return;
    length = JSSTRING_LENGTH(str);
    if (length == 0 || !ENSURE_STRING_BUFFER(sb, length))
        return;
    bp = sb->ptr;
    js_strncpy(bp, JSSTRING_CHARS(str), length);
    bp += length;
    *bp = 0;
    sb->ptr = bp;
}

Here is the caller graph for this function:

JSTokenType js_CheckKeyword ( const jschar chars,
size_t  length 
)

Definition at line 136 of file jsscan.c.

{
    const struct keyword *kw;

    JS_ASSERT(length != 0);
    kw = FindKeyword(str, length);
    return kw ? kw->tokentype : TOK_EOF;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 800 of file jsscan.c.

{
    sb->free(sb);
}

Here is the caller graph for this function:

JS_FRIEND_API ( void  ) const

Definition at line 1080 of file jsscan.c.

{
    JSTokenType tt;
    int32 c, qc;
    JSToken *tp;
    JSAtom *atom;
    JSBool hadUnicodeEscape;
    const struct keyword *kw;

#define INIT_TOKENBUF()     (ts->tokenbuf.ptr = ts->tokenbuf.base)
#define TOKENBUF_LENGTH()   PTRDIFF(ts->tokenbuf.ptr, ts->tokenbuf.base, jschar)
#define TOKENBUF_OK()       STRING_BUFFER_OK(&ts->tokenbuf)
#define TOKENBUF_TO_ATOM()  (TOKENBUF_OK()                                    \
                             ? js_AtomizeChars(cx,                            \
                                               TOKENBUF_BASE(),               \
                                               TOKENBUF_LENGTH(),             \
                                               0)                             \
                             : NULL)
#define ADD_TO_TOKENBUF(c)  FastAppendChar(&ts->tokenbuf, (jschar) (c))

/* The following 4 macros should only be used when TOKENBUF_OK() is true. */
#define TOKENBUF_BASE()     (ts->tokenbuf.base)
#define TOKENBUF_CHAR(i)    (ts->tokenbuf.base[i])
#define TRIM_TOKENBUF(i)    (ts->tokenbuf.ptr = ts->tokenbuf.base + i)
#define NUL_TERM_TOKENBUF() (*ts->tokenbuf.ptr = 0)

    /* Check for a pushed-back token resulting from mismatching lookahead. */
    while (ts->lookahead != 0) {
        JS_ASSERT(!(ts->flags & TSF_XMLTEXTMODE));
        ts->lookahead--;
        ts->cursor = (ts->cursor + 1) & NTOKENS_MASK;
        tt = CURRENT_TOKEN(ts).type;
        if (tt != TOK_EOL || (ts->flags & TSF_NEWLINES))
            return tt;
    }

    /* If there was a fatal error, keep returning TOK_ERROR. */
    if (ts->flags & TSF_ERROR)
        return TOK_ERROR;

#if JS_HAS_XML_SUPPORT
    if (ts->flags & TSF_XMLTEXTMODE) {
        tt = TOK_XMLSPACE;      /* veto if non-space, return TOK_XMLTEXT */
        tp = NewToken(ts, 0);
        INIT_TOKENBUF();
        qc = (ts->flags & TSF_XMLONLYMODE) ? '<' : '{';

        while ((c = GetChar(ts)) != qc && c != '<' && c != EOF) {
            if (c == '&' && qc == '<') {
                if (!GetXMLEntity(cx, ts))
                    goto error;
                tt = TOK_XMLTEXT;
                continue;
            }

            if (!JS_ISXMLSPACE(c))
                tt = TOK_XMLTEXT;
            ADD_TO_TOKENBUF(c);
        }
        UngetChar(ts, c);

        if (TOKENBUF_LENGTH() == 0) {
            atom = NULL;
        } else {
            atom = TOKENBUF_TO_ATOM();
            if (!atom)
                goto error;
        }
        tp->pos.end.lineno = (uint16)ts->lineno;
        tp->t_op = JSOP_STRING;
        tp->t_atom = atom;
        goto out;
    }

    if (ts->flags & TSF_XMLTAGMODE) {
        tp = NewToken(ts, 0);
        c = GetChar(ts);
        if (JS_ISXMLSPACE(c)) {
            do {
                c = GetChar(ts);
            } while (JS_ISXMLSPACE(c));
            UngetChar(ts, c);
            tt = TOK_XMLSPACE;
            goto out;
        }

        if (c == EOF) {
            tt = TOK_EOF;
            goto out;
        }

        INIT_TOKENBUF();
        if (JS_ISXMLNSSTART(c)) {
            JSBool sawColon = JS_FALSE;

            ADD_TO_TOKENBUF(c);
            while ((c = GetChar(ts)) != EOF && JS_ISXMLNAME(c)) {
                if (c == ':') {
                    int nextc;

                    if (sawColon ||
                        (nextc = PeekChar(ts),
                         ((ts->flags & TSF_XMLONLYMODE) || nextc != '{') &&
                         !JS_ISXMLNAME(nextc))) {
                        js_ReportCompileErrorNumber(cx, ts,
                                                    JSREPORT_TS |
                                                    JSREPORT_ERROR,
                                                    JSMSG_BAD_XML_QNAME);
                        goto error;
                    }
                    sawColon = JS_TRUE;
                }

                ADD_TO_TOKENBUF(c);
            }

            UngetChar(ts, c);
            atom = TOKENBUF_TO_ATOM();
            if (!atom)
                goto error;
            tp->t_op = JSOP_STRING;
            tp->t_atom = atom;
            tt = TOK_XMLNAME;
            goto out;
        }

        switch (c) {
          case '{':
            if (ts->flags & TSF_XMLONLYMODE)
                goto bad_xml_char;
            tt = TOK_LC;
            goto out;

          case '=':
            tt = TOK_ASSIGN;
            goto out;

          case '"':
          case '\'':
            qc = c;
            while ((c = GetChar(ts)) != qc) {
                if (c == EOF) {
                    js_ReportCompileErrorNumber(cx, ts,
                                                JSREPORT_TS | JSREPORT_ERROR,
                                                JSMSG_UNTERMINATED_STRING);
                    goto error;
                }

                /*
                 * XML attribute values are double-quoted when pretty-printed,
                 * so escape " if it is expressed directly in a single-quoted
                 * attribute value.
                 */
                if (c == '"' && !(ts->flags & TSF_XMLONLYMODE)) {
                    JS_ASSERT(qc == '\'');
                    js_AppendCString(&ts->tokenbuf, js_quot_entity_str);
                    continue;
                }

                if (c == '&' && (ts->flags & TSF_XMLONLYMODE)) {
                    if (!GetXMLEntity(cx, ts))
                        goto error;
                    continue;
                }

                ADD_TO_TOKENBUF(c);
            }
            atom = TOKENBUF_TO_ATOM();
            if (!atom)
                goto error;
            tp->pos.end.lineno = (uint16)ts->lineno;
            tp->t_op = JSOP_STRING;
            tp->t_atom = atom;
            tt = TOK_XMLATTR;
            goto out;

          case '>':
            tt = TOK_XMLTAGC;
            goto out;

          case '/':
            if (MatchChar(ts, '>')) {
                tt = TOK_XMLPTAGC;
                goto out;
            }
            /* FALL THROUGH */

          bad_xml_char:
          default:
            js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR,
                                        JSMSG_BAD_XML_CHARACTER);
            goto error;
        }
        /* NOTREACHED */
    }
#endif /* JS_HAS_XML_SUPPORT */

retry:
    do {
        c = GetChar(ts);
        if (c == '\n') {
            ts->flags &= ~TSF_DIRTYLINE;
            if (ts->flags & TSF_NEWLINES)
                break;
        }
    } while (ScanAsSpace(c));

    tp = NewToken(ts, -1);
    if (c == EOF) {
        tt = TOK_EOF;
        goto out;
    }

    hadUnicodeEscape = JS_FALSE;
    if (JS_ISIDSTART(c) ||
        (c == '\\' &&
         (c = GetUnicodeEscape(ts),
          hadUnicodeEscape = JS_ISIDSTART(c)))) {
        INIT_TOKENBUF();
        for (;;) {
            ADD_TO_TOKENBUF(c);
            c = GetChar(ts);
            if (c == '\\') {
                c = GetUnicodeEscape(ts);
                if (!JS_ISIDENT(c))
                    break;
                hadUnicodeEscape = JS_TRUE;
            } else {
                if (!JS_ISIDENT(c))
                    break;
            }
        }
        UngetChar(ts, c);

        /*
         * Check for keywords unless we saw Unicode escape or parser asks
         * to ignore keywords.
         */
        if (!hadUnicodeEscape &&
            !(ts->flags & TSF_KEYWORD_IS_NAME) &&
            TOKENBUF_OK() &&
            (kw = FindKeyword(TOKENBUF_BASE(), TOKENBUF_LENGTH()))) {
            if (kw->tokentype == TOK_RESERVED) {
                if (!js_ReportCompileErrorNumber(cx, ts,
                                                 JSREPORT_TS |
                                                 JSREPORT_WARNING |
                                                 JSREPORT_STRICT,
                                                 JSMSG_RESERVED_ID,
                                                 kw->chars)) {
                    goto error;
                }
            } else if (kw->version <= JSVERSION_NUMBER(cx)) {
                tt = kw->tokentype;
                tp->t_op = (JSOp) kw->op;
                goto out;
            }
        }

        atom = TOKENBUF_TO_ATOM();
        if (!atom)
            goto error;
        tp->t_op = JSOP_NAME;
        tp->t_atom = atom;
        tt = TOK_NAME;
        goto out;
    }

    if (JS7_ISDEC(c) || (c == '.' && JS7_ISDEC(PeekChar(ts)))) {
        jsint radix;
        const jschar *endptr;
        jsdouble dval;

        radix = 10;
        INIT_TOKENBUF();

        if (c == '0') {
            ADD_TO_TOKENBUF(c);
            c = GetChar(ts);
            if (JS_TOLOWER(c) == 'x') {
                ADD_TO_TOKENBUF(c);
                c = GetChar(ts);
                radix = 16;
            } else if (JS7_ISDEC(c)) {
                radix = 8;
            }
        }

        while (JS7_ISHEX(c)) {
            if (radix < 16) {
                if (JS7_ISLET(c))
                    break;

                /*
                 * We permit 08 and 09 as decimal numbers, which makes our
                 * behaviour a superset of the ECMA numeric grammar.  We might
                 * not always be so permissive, so we warn about it.
                 */
                if (radix == 8 && c >= '8') {
                    if (!js_ReportCompileErrorNumber(cx, ts,
                                                     JSREPORT_TS |
                                                     JSREPORT_WARNING,
                                                     JSMSG_BAD_OCTAL,
                                                     c == '8' ? "08" : "09")) {
                        goto error;
                    }
                    radix = 10;
                }
            }
            ADD_TO_TOKENBUF(c);
            c = GetChar(ts);
        }

        if (radix == 10 && (c == '.' || JS_TOLOWER(c) == 'e')) {
            if (c == '.') {
                do {
                    ADD_TO_TOKENBUF(c);
                    c = GetChar(ts);
                } while (JS7_ISDEC(c));
            }
            if (JS_TOLOWER(c) == 'e') {
                ADD_TO_TOKENBUF(c);
                c = GetChar(ts);
                if (c == '+' || c == '-') {
                    ADD_TO_TOKENBUF(c);
                    c = GetChar(ts);
                }
                if (!JS7_ISDEC(c)) {
                    js_ReportCompileErrorNumber(cx, ts,
                                                JSREPORT_TS | JSREPORT_ERROR,
                                                JSMSG_MISSING_EXPONENT);
                    goto error;
                }
                do {
                    ADD_TO_TOKENBUF(c);
                    c = GetChar(ts);
                } while (JS7_ISDEC(c));
            }
        }

        /* Put back the next char and NUL-terminate tokenbuf for js_strto*. */
        UngetChar(ts, c);
        ADD_TO_TOKENBUF(0);

        if (!TOKENBUF_OK())
            goto error;
        if (radix == 10) {
            if (!js_strtod(cx, TOKENBUF_BASE(), &endptr, &dval)) {
                js_ReportCompileErrorNumber(cx, ts,
                                            JSREPORT_TS | JSREPORT_ERROR,
                                            JSMSG_OUT_OF_MEMORY);
                goto error;
            }
        } else {
            if (!js_strtointeger(cx, TOKENBUF_BASE(), &endptr, radix, &dval)) {
                js_ReportCompileErrorNumber(cx, ts,
                                            JSREPORT_TS | JSREPORT_ERROR,
                                            JSMSG_OUT_OF_MEMORY);
                goto error;
            }
        }
        tp->t_dval = dval;
        tt = TOK_NUMBER;
        goto out;
    }

    if (c == '"' || c == '\'') {
        qc = c;
        INIT_TOKENBUF();
        while ((c = GetChar(ts)) != qc) {
            if (c == '\n' || c == EOF) {
                UngetChar(ts, c);
                js_ReportCompileErrorNumber(cx, ts,
                                            JSREPORT_TS | JSREPORT_ERROR,
                                            JSMSG_UNTERMINATED_STRING);
                goto error;
            }
            if (c == '\\') {
                switch (c = GetChar(ts)) {
                  case 'b': c = '\b'; break;
                  case 'f': c = '\f'; break;
                  case 'n': c = '\n'; break;
                  case 'r': c = '\r'; break;
                  case 't': c = '\t'; break;
                  case 'v': c = '\v'; break;

                  default:
                    if ('0' <= c && c < '8') {
                        int32 val = JS7_UNDEC(c);

                        c = PeekChar(ts);
                        if ('0' <= c && c < '8') {
                            val = 8 * val + JS7_UNDEC(c);
                            GetChar(ts);
                            c = PeekChar(ts);
                            if ('0' <= c && c < '8') {
                                int32 save = val;
                                val = 8 * val + JS7_UNDEC(c);
                                if (val <= 0377)
                                    GetChar(ts);
                                else
                                    val = save;
                            }
                        }

                        c = (jschar)val;
                    } else if (c == 'u') {
                        jschar cp[4];
                        if (PeekChars(ts, 4, cp) &&
                            JS7_ISHEX(cp[0]) && JS7_ISHEX(cp[1]) &&
                            JS7_ISHEX(cp[2]) && JS7_ISHEX(cp[3])) {
                            c = (((((JS7_UNHEX(cp[0]) << 4)
                                    + JS7_UNHEX(cp[1])) << 4)
                                  + JS7_UNHEX(cp[2])) << 4)
                                + JS7_UNHEX(cp[3]);
                            SkipChars(ts, 4);
                        }
                    } else if (c == 'x') {
                        jschar cp[2];
                        if (PeekChars(ts, 2, cp) &&
                            JS7_ISHEX(cp[0]) && JS7_ISHEX(cp[1])) {
                            c = (JS7_UNHEX(cp[0]) << 4) + JS7_UNHEX(cp[1]);
                            SkipChars(ts, 2);
                        }
                    } else if (c == '\n' && JS_VERSION_IS_ECMA(cx)) {
                        /* ECMA follows C by removing escaped newlines. */
                        continue;
                    }
                    break;
                }
            }
            ADD_TO_TOKENBUF(c);
        }
        atom = TOKENBUF_TO_ATOM();
        if (!atom)
            goto error;
        tp->pos.end.lineno = (uint16)ts->lineno;
        tp->t_op = JSOP_STRING;
        tp->t_atom = atom;
        tt = TOK_STRING;
        goto out;
    }

    switch (c) {
      case '\n': tt = TOK_EOL; goto eol_out;
      case ';':  tt = TOK_SEMI; break;
      case '[':  tt = TOK_LB; break;
      case ']':  tt = TOK_RB; break;
      case '{':  tt = TOK_LC; break;
      case '}':  tt = TOK_RC; break;
      case '(':  tt = TOK_LP; break;
      case ')':  tt = TOK_RP; break;
      case ',':  tt = TOK_COMMA; break;
      case '?':  tt = TOK_HOOK; break;

      case '.':
#if JS_HAS_XML_SUPPORT
        if (MatchChar(ts, c))
            tt = TOK_DBLDOT;
        else
#endif
            tt = TOK_DOT;
        break;

      case ':':
#if JS_HAS_XML_SUPPORT
        if (MatchChar(ts, c)) {
            tt = TOK_DBLCOLON;
            break;
        }
#endif
        /*
         * Default so compiler can modify to JSOP_GETTER if 'p getter: v' in an
         * object initializer, likewise for setter.
         */
        tp->t_op = JSOP_NOP;
        tt = TOK_COLON;
        break;

      case '|':
        if (MatchChar(ts, c)) {
            tt = TOK_OR;
        } else if (MatchChar(ts, '=')) {
            tp->t_op = JSOP_BITOR;
            tt = TOK_ASSIGN;
        } else {
            tt = TOK_BITOR;
        }
        break;

      case '^':
        if (MatchChar(ts, '=')) {
            tp->t_op = JSOP_BITXOR;
            tt = TOK_ASSIGN;
        } else {
            tt = TOK_BITXOR;
        }
        break;

      case '&':
        if (MatchChar(ts, c)) {
            tt = TOK_AND;
        } else if (MatchChar(ts, '=')) {
            tp->t_op = JSOP_BITAND;
            tt = TOK_ASSIGN;
        } else {
            tt = TOK_BITAND;
        }
        break;

      case '=':
        if (MatchChar(ts, c)) {
            tp->t_op = MatchChar(ts, c) ? JSOP_NEW_EQ : (JSOp)cx->jsop_eq;
            tt = TOK_EQOP;
        } else {
            tp->t_op = JSOP_NOP;
            tt = TOK_ASSIGN;
        }
        break;

      case '!':
        if (MatchChar(ts, '=')) {
            tp->t_op = MatchChar(ts, '=') ? JSOP_NEW_NE : (JSOp)cx->jsop_ne;
            tt = TOK_EQOP;
        } else {
            tp->t_op = JSOP_NOT;
            tt = TOK_UNARYOP;
        }
        break;

#if JS_HAS_XML_SUPPORT
      case '@':
        tt = TOK_AT;
        break;
#endif

      case '<':
#if JS_HAS_XML_SUPPORT
        /*
         * After much testing, it's clear that Postel's advice to protocol
         * designers ("be liberal in what you accept, and conservative in what
         * you send") invites a natural-law repercussion for JS as "protocol":
         *
         * "If you are liberal in what you accept, others will utterly fail to
         *  be conservative in what they send."
         *
         * Which means you will get <!-- comments to end of line in the middle
         * of .js files, and after if conditions whose then statements are on
         * the next line, and other wonders.  See at least the following bugs:
         * https://bugzilla.mozilla.org/show_bug.cgi?id=309242
         * https://bugzilla.mozilla.org/show_bug.cgi?id=309712
         * https://bugzilla.mozilla.org/show_bug.cgi?id=310993
         *
         * So without JSOPTION_XML, we never scan an XML comment or CDATA
         * literal.  We always scan <! as the start of an HTML comment hack
         * to end of line, used since Netscape 2 to hide script tag content
         * from script-unaware browsers.
         */
        if ((ts->flags & TSF_OPERAND) &&
            (JS_HAS_XML_OPTION(cx) || PeekChar(ts) != '!')) {
            /* Check for XML comment or CDATA section. */
            if (MatchChar(ts, '!')) {
                INIT_TOKENBUF();

                /* Scan XML comment. */
                if (MatchChar(ts, '-')) {
                    if (!MatchChar(ts, '-'))
                        goto bad_xml_markup;
                    while ((c = GetChar(ts)) != '-' || !MatchChar(ts, '-')) {
                        if (c == EOF)
                            goto bad_xml_markup;
                        ADD_TO_TOKENBUF(c);
                    }
                    tt = TOK_XMLCOMMENT;
                    tp->t_op = JSOP_XMLCOMMENT;
                    goto finish_xml_markup;
                }

                /* Scan CDATA section. */
                if (MatchChar(ts, '[')) {
                    jschar cp[6];
                    if (PeekChars(ts, 6, cp) &&
                        cp[0] == 'C' &&
                        cp[1] == 'D' &&
                        cp[2] == 'A' &&
                        cp[3] == 'T' &&
                        cp[4] == 'A' &&
                        cp[5] == '[') {
                        SkipChars(ts, 6);
                        while ((c = GetChar(ts)) != ']' ||
                               !PeekChars(ts, 2, cp) ||
                               cp[0] != ']' ||
                               cp[1] != '>') {
                            if (c == EOF)
                                goto bad_xml_markup;
                            ADD_TO_TOKENBUF(c);
                        }
                        GetChar(ts);            /* discard ] but not > */
                        tt = TOK_XMLCDATA;
                        tp->t_op = JSOP_XMLCDATA;
                        goto finish_xml_markup;
                    }
                    goto bad_xml_markup;
                }
            }

            /* Check for processing instruction. */
            if (MatchChar(ts, '?')) {
                JSBool inTarget = JS_TRUE;
                size_t targetLength = 0;
                ptrdiff_t contentIndex = -1;

                INIT_TOKENBUF();
                while ((c = GetChar(ts)) != '?' || PeekChar(ts) != '>') {
                    if (c == EOF)
                        goto bad_xml_markup;
                    if (inTarget) {
                        if (JS_ISXMLSPACE(c)) {
                            if (TOKENBUF_LENGTH() == 0)
                                goto bad_xml_markup;
                            inTarget = JS_FALSE;
                        } else {
                            if (!((TOKENBUF_LENGTH() == 0)
                                  ? JS_ISXMLNSSTART(c)
                                  : JS_ISXMLNS(c))) {
                                goto bad_xml_markup;
                            }
                            ++targetLength;
                        }
                    } else {
                        if (contentIndex < 0 && !JS_ISXMLSPACE(c))
                            contentIndex = TOKENBUF_LENGTH();
                    }
                    ADD_TO_TOKENBUF(c);
                }
                if (targetLength == 0)
                    goto bad_xml_markup;
                if (!TOKENBUF_OK())
                    goto error;
                if (contentIndex < 0) {
                    atom = cx->runtime->atomState.emptyAtom;
                } else {
                    atom = js_AtomizeChars(cx,
                                           &TOKENBUF_CHAR(contentIndex),
                                           TOKENBUF_LENGTH() - contentIndex,
                                           0);
                    if (!atom)
                        goto error;
                }
                TRIM_TOKENBUF(targetLength);
                tp->t_atom2 = atom;
                tt = TOK_XMLPI;

        finish_xml_markup:
                if (!MatchChar(ts, '>'))
                    goto bad_xml_markup;
                atom = TOKENBUF_TO_ATOM();
                if (!atom)
                    goto error;
                tp->t_atom = atom;
                tp->pos.end.lineno = (uint16)ts->lineno;
                goto out;
            }

            /* An XML start-of-tag character. */
            tt = MatchChar(ts, '/') ? TOK_XMLETAGO : TOK_XMLSTAGO;
            goto out;

        bad_xml_markup:
            js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR,
                                        JSMSG_BAD_XML_MARKUP);
            goto error;
        }
#endif /* JS_HAS_XML_SUPPORT */

        /* NB: treat HTML begin-comment as comment-till-end-of-line */
        if (MatchChar(ts, '!')) {
            if (MatchChar(ts, '-')) {
                if (MatchChar(ts, '-')) {
                    ts->flags |= TSF_IN_HTML_COMMENT;
                    goto skipline;
                }
                UngetChar(ts, '-');
            }
            UngetChar(ts, '!');
        }
        if (MatchChar(ts, c)) {
            tp->t_op = JSOP_LSH;
            tt = MatchChar(ts, '=') ? TOK_ASSIGN : TOK_SHOP;
        } else {
            tp->t_op = MatchChar(ts, '=') ? JSOP_LE : JSOP_LT;
            tt = TOK_RELOP;
        }
        break;

      case '>':
        if (MatchChar(ts, c)) {
            tp->t_op = MatchChar(ts, c) ? JSOP_URSH : JSOP_RSH;
            tt = MatchChar(ts, '=') ? TOK_ASSIGN : TOK_SHOP;
        } else {
            tp->t_op = MatchChar(ts, '=') ? JSOP_GE : JSOP_GT;
            tt = TOK_RELOP;
        }
        break;

      case '*':
        tp->t_op = JSOP_MUL;
        tt = MatchChar(ts, '=') ? TOK_ASSIGN : TOK_STAR;
        break;

      case '/':
        if (MatchChar(ts, '/')) {
            /*
             * Hack for source filters such as the Mozilla XUL preprocessor:
             * "//@line 123\n" sets the number of the *next* line after the
             * comment to 123.
             */
            if (JS_HAS_ATLINE_OPTION(cx)) {
                jschar cp[5];
                uintN i, line, temp;
                char filename[1024];

                if (PeekChars(ts, 5, cp) &&
                    cp[0] == '@' &&
                    cp[1] == 'l' &&
                    cp[2] == 'i' &&
                    cp[3] == 'n' &&
                    cp[4] == 'e') {
                    SkipChars(ts, 5);
                    while ((c = GetChar(ts)) != '\n' && ScanAsSpace(c))
                        continue;
                    if (JS7_ISDEC(c)) {
                        line = JS7_UNDEC(c);
                        while ((c = GetChar(ts)) != EOF && JS7_ISDEC(c)) {
                            temp = 10 * line + JS7_UNDEC(c);
                            if (temp < line) {
                                /* Ignore overlarge line numbers. */
                                goto skipline;
                            }
                            line = temp;
                        }
                        while (c != '\n' && ScanAsSpace(c))
                            c = GetChar(ts);
                        i = 0;
                        if (c == '"') {
                            while ((c = GetChar(ts)) != EOF && c != '"') {
                                if (c == '\n') {
                                    UngetChar(ts, c);
                                    goto skipline;
                                }
                                if ((c >> 8) != 0 || i >= sizeof filename - 1)
                                    goto skipline;
                                filename[i++] = (char) c;
                            }
                            if (c == '"') {
                                while ((c = GetChar(ts)) != '\n' &&
                                       ScanAsSpace(c)) {
                                    continue;
                                }
                            }
                        }
                        filename[i] = '\0';
                        if (c == '\n') {
                            if (i > 0) {
                                if (ts->flags & TSF_OWNFILENAME)
                                    JS_free(cx, (void *) ts->filename);
                                ts->filename = JS_strdup(cx, filename);
                                if (!ts->filename)
                                    goto error;
                                ts->flags |= TSF_OWNFILENAME;
                            }
                            ts->lineno = line;
                        }
                    }
                    UngetChar(ts, c);
                }
            }

skipline:
            /* Optimize line skipping if we are not in an HTML comment. */
            if (ts->flags & TSF_IN_HTML_COMMENT) {
                while ((c = GetChar(ts)) != EOF && c != '\n') {
                    if (c == '-' && MatchChar(ts, '-') && MatchChar(ts, '>'))
                        ts->flags &= ~TSF_IN_HTML_COMMENT;
                }
            } else {
                while ((c = GetChar(ts)) != EOF && c != '\n')
                    continue;
            }
            UngetChar(ts, c);
            ts->cursor = (ts->cursor - 1) & NTOKENS_MASK;
            goto retry;
        }

        if (MatchChar(ts, '*')) {
            while ((c = GetChar(ts)) != EOF &&
                   !(c == '*' && MatchChar(ts, '/'))) {
                /* Ignore all characters until comment close. */
            }
            if (c == EOF) {
                js_ReportCompileErrorNumber(cx, ts,
                                            JSREPORT_TS | JSREPORT_ERROR,
                                            JSMSG_UNTERMINATED_COMMENT);
                goto error;
            }
            ts->cursor = (ts->cursor - 1) & NTOKENS_MASK;
            goto retry;
        }

        if (ts->flags & TSF_OPERAND) {
            JSObject *obj;
            uintN flags;
            JSBool inCharClass = JS_FALSE;

            INIT_TOKENBUF();
            for (;;) {
                c = GetChar(ts);
                if (c == '\n' || c == EOF) {
                    UngetChar(ts, c);
                    js_ReportCompileErrorNumber(cx, ts,
                                                JSREPORT_TS | JSREPORT_ERROR,
                                                JSMSG_UNTERMINATED_REGEXP);
                    goto error;
                }
                if (c == '\\') {
                    ADD_TO_TOKENBUF(c);
                    c = GetChar(ts);
                } else if (c == '[') {
                    inCharClass = JS_TRUE;
                } else if (c == ']') {
                    inCharClass = JS_FALSE;
                } else if (c == '/' && !inCharClass) {
                    /* For compat with IE, allow unescaped / in char classes. */
                    break;
                }
                ADD_TO_TOKENBUF(c);
            }
            for (flags = 0; ; ) {
                if (MatchChar(ts, 'g'))
                    flags |= JSREG_GLOB;
                else if (MatchChar(ts, 'i'))
                    flags |= JSREG_FOLD;
                else if (MatchChar(ts, 'm'))
                    flags |= JSREG_MULTILINE;
                else
                    break;
            }
            c = PeekChar(ts);
            if (JS7_ISLET(c)) {
                tp->ptr = ts->linebuf.ptr - 1;
                js_ReportCompileErrorNumber(cx, ts,
                                            JSREPORT_TS | JSREPORT_ERROR,
                                            JSMSG_BAD_REGEXP_FLAG);
                (void) GetChar(ts);
                goto error;
            }
            /* XXXbe fix jsregexp.c so it doesn't depend on NUL termination */
            if (!TOKENBUF_OK())
                goto error;
            NUL_TERM_TOKENBUF();
            obj = js_NewRegExpObject(cx, ts,
                                     TOKENBUF_BASE(),
                                     TOKENBUF_LENGTH(),
                                     flags);
            if (!obj)
                goto error;
            atom = js_AtomizeObject(cx, obj, 0);
            if (!atom)
                goto error;

            /*
             * If the regexp's script is one-shot, we can avoid the extra
             * fork-on-exec costs of JSOP_REGEXP by selecting JSOP_OBJECT.
             * Otherwise, to avoid incorrect proto, parent, and lastIndex
             * sharing among threads and sequentially across re-execution,
             * select JSOP_REGEXP.
             */
            tp->t_op = (cx->fp->flags & (JSFRAME_EVAL | JSFRAME_COMPILE_N_GO))
                       ? JSOP_OBJECT
                       : JSOP_REGEXP;
            tp->t_atom = atom;
            tt = TOK_OBJECT;
            break;
        }

        tp->t_op = JSOP_DIV;
        tt = MatchChar(ts, '=') ? TOK_ASSIGN : TOK_DIVOP;
        break;

      case '%':
        tp->t_op = JSOP_MOD;
        tt = MatchChar(ts, '=') ? TOK_ASSIGN : TOK_DIVOP;
        break;

      case '~':
        tp->t_op = JSOP_BITNOT;
        tt = TOK_UNARYOP;
        break;

      case '+':
        if (MatchChar(ts, '=')) {
            tp->t_op = JSOP_ADD;
            tt = TOK_ASSIGN;
        } else if (MatchChar(ts, c)) {
            tt = TOK_INC;
        } else {
            tp->t_op = JSOP_POS;
            tt = TOK_PLUS;
        }
        break;

      case '-':
        if (MatchChar(ts, '=')) {
            tp->t_op = JSOP_SUB;
            tt = TOK_ASSIGN;
        } else if (MatchChar(ts, c)) {
            if (PeekChar(ts) == '>' && !(ts->flags & TSF_DIRTYLINE)) {
                ts->flags &= ~TSF_IN_HTML_COMMENT;
                goto skipline;
            }
            tt = TOK_DEC;
        } else {
            tp->t_op = JSOP_NEG;
            tt = TOK_MINUS;
        }
        break;

#if JS_HAS_SHARP_VARS
      case '#':
      {
        uint32 n;

        c = GetChar(ts);
        if (!JS7_ISDEC(c)) {
            UngetChar(ts, c);
            goto badchar;
        }
        n = (uint32)JS7_UNDEC(c);
        for (;;) {
            c = GetChar(ts);
            if (!JS7_ISDEC(c))
                break;
            n = 10 * n + JS7_UNDEC(c);
            if (n >= UINT16_LIMIT) {
                js_ReportCompileErrorNumber(cx, ts,
                                            JSREPORT_TS | JSREPORT_ERROR,
                                            JSMSG_SHARPVAR_TOO_BIG);
                goto error;
            }
        }
        tp->t_dval = (jsdouble) n;
        if (JS_HAS_STRICT_OPTION(cx) &&
            (c == '=' || c == '#')) {
            char buf[20];
            JS_snprintf(buf, sizeof buf, "#%u%c", n, c);
            if (!js_ReportCompileErrorNumber(cx, ts,
                                             JSREPORT_TS |
                                             JSREPORT_WARNING |
                                             JSREPORT_STRICT,
                                             JSMSG_DEPRECATED_USAGE,
                                             buf)) {
                goto error;
            }
        }
        if (c == '=')
            tt = TOK_DEFSHARP;
        else if (c == '#')
            tt = TOK_USESHARP;
        else
            goto badchar;
        break;
      }
#endif /* JS_HAS_SHARP_VARS */

#if JS_HAS_SHARP_VARS || JS_HAS_XML_SUPPORT
      badchar:
#endif

      default:
        js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR,
                                    JSMSG_ILLEGAL_CHARACTER);
        goto error;
    }

out:
    JS_ASSERT(tt != TOK_EOL);
    ts->flags |= TSF_DIRTYLINE;

eol_out:
    if (!STRING_BUFFER_OK(&ts->tokenbuf))
        tt = TOK_ERROR;
    JS_ASSERT(tt < TOK_LIMIT);
    tp->pos.end.index = ts->linepos +
                        PTRDIFF(ts->linebuf.ptr, ts->linebuf.base, jschar) -
                        ts->ungetpos;
    tp->type = tt;
    return tt;

error:
    tt = TOK_ERROR;
    ts->flags |= TSF_ERROR;
    goto out;

#undef INIT_TOKENBUF
#undef TOKENBUF_LENGTH
#undef TOKENBUF_OK
#undef TOKENBUF_TO_ATOM
#undef ADD_TO_TOKENBUF
#undef TOKENBUF_BASE
#undef TOKENBUF_CHAR
#undef TRIM_TOKENBUF
#undef NUL_TERM_TOKENBUF
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 791 of file jsscan.c.

{
    sb->base = sb->limit = sb->ptr = NULL;
    sb->data = NULL;
    sb->grow = GrowStringBuffer;
    sb->free = FreeStringBuffer;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 2102 of file jsscan.c.

{
    if (js_GetToken(cx, ts) == tt)
        return JS_TRUE;
    js_UngetToken(ts);
    return JS_FALSE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

JSTokenStream* js_NewTokenStream ( JSContext cx,
const jschar base,
size_t  length,
const char *  filename,
uintN  lineno,
JSPrincipals principals 
)

Definition at line 155 of file jsscan.c.

{
    JSTokenStream *ts;

    ts = js_NewBufferTokenStream(cx, base, length);
    if (!ts)
        return NULL;
    ts->filename = filename;
    ts->lineno = lineno;
    if (principals)
        JSPRINCIPALS_HOLD(cx, principals);
    ts->principals = principals;
    return ts;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1004 of file jsscan.c.

{
    JSTokenType tt;

    if (ts->lookahead != 0) {
        tt = ts->tokens[(ts->cursor + ts->lookahead) & NTOKENS_MASK].type;
    } else {
        tt = js_GetToken(cx, ts);
        js_UngetToken(ts);
    }
    return tt;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1018 of file jsscan.c.

{
    JSTokenType tt;

    if (!ON_CURRENT_LINE(ts, CURRENT_TOKEN(ts).pos))
        return TOK_EOL;
    ts->flags |= TSF_NEWLINES;
    tt = js_PeekToken(cx, ts);
    ts->flags &= ~TSF_NEWLINES;
    return tt;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void js_RepeatChar ( JSStringBuffer sb,
jschar  c,
uintN  count 
)

Definition at line 836 of file jsscan.c.

{
    jschar *bp;

    if (!STRING_BUFFER_OK(sb) || count == 0)
        return;
    if (!ENSURE_STRING_BUFFER(sb, count))
        return;
    for (bp = sb->ptr; count; --count)
        *bp++ = c;
    *bp = 0;
    sb->ptr = bp;
}

Here is the caller graph for this function:

JSBool js_ReportCompileErrorNumber ( JSContext cx,
void handle,
uintN  flags,
uintN  errorNumber,
  ... 
)

Definition at line 707 of file jsscan.c.

{
    va_list ap;
    JSErrorReport report;
    JSBool warning;

    if ((flags & JSREPORT_STRICT) && !JS_HAS_STRICT_OPTION(cx))
        return JS_TRUE;

    va_start(ap, errorNumber);
    warning = ReportCompileErrorNumber(cx, handle, flags, errorNumber,
                                       &report, JS_TRUE, ap);
    va_end(ap);

    /*
     * We have to do this here because js_ReportCompileErrorNumberUC doesn't
     * need to do this.
     */
    if (report.messageArgs) {
        int i = 0;
        while (report.messageArgs[i])
            JS_free(cx, (void *)report.messageArgs[i++]);
        JS_free(cx, (void *)report.messageArgs);
    }

    return warning;
}

Here is the call graph for this function:

Here is the caller graph for this function:

JSBool js_ReportCompileErrorNumberUC ( JSContext cx,
void handle,
uintN  flags,
uintN  errorNumber,
  ... 
)

Definition at line 737 of file jsscan.c.

{
    va_list ap;
    JSErrorReport report;
    JSBool warning;

    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);
    va_end(ap);

    if (report.messageArgs)
        JS_free(cx, (void *)report.messageArgs);

    return warning;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 2094 of file jsscan.c.

{
    JS_ASSERT(ts->lookahead < NTOKENS_MASK);
    ts->lookahead++;
    ts->cursor = (ts->cursor - 1) & NTOKENS_MASK;
}

Here is the caller graph for this function:


Variable Documentation

Definition at line 313 of file jsscan.h.

Definition at line 316 of file jsscan.h.

Definition at line 322 of file jsscan.h.

const char* filename

Definition at line 316 of file jsscan.h.

Definition at line 313 of file jsscan.h.

Definition at line 322 of file jsscan.h.

Definition at line 319 of file jsscan.h.