if (!hadUnicodeEscape && atom->kwindex >= 0) { struct keyword *kw;  kw = &keywords[atom->kwindex]; tp->t_op = (JSOp) kw->op; RETURN(kw->tokentype);
if (!hadUnicodeEscape && ATOM_KEYWORD(atom)) { struct keyword *kw = ATOM_KEYWORD(atom);  if (JSVERSION_IS_ECMA(cx->version) || kw->version <= cx->version) { tp->t_op = (JSOp) kw->op; RETURN(kw->tokentype); }
js_GetToken(JSContext *cx, JSTokenStream *ts){    JSTokenType tt;    JSToken *tp;    int32 c;    JSAtom *atom;    JSBool hadUnicodeEscape;#define INIT_TOKENBUF(tb)   ((tb)->ptr = (tb)->base)#define FINISH_TOKENBUF(tb) if (!AddToTokenBuf(cx, tb, 0)) RETURN(TOK_ERROR)#define TOKEN_LENGTH(tb)    ((tb)->ptr - (tb)->base - 1)#define RETURN(tt)          { if (tt == TOK_ERROR) ts->flags |= TSF_ERROR;    \			      tp->pos.end.index = ts->linepos +               \				  (ts->linebuf.ptr - ts->linebuf.base) -      \				  ts->ungetpos;                               \			      return (tp->type = tt); }    /* If there was a fatal error, keep returning TOK_ERROR. */    if (ts->flags & TSF_ERROR)	return TOK_ERROR;    /* Check for a pushed-back token resulting from mismatching lookahead. */    while (ts->lookahead != 0) {        ts->lookahead--;        ts->cursor = (ts->cursor + 1) & NTOKENS_MASK;        tt = CURRENT_TOKEN(ts).type;        if (tt != TOK_EOL || (ts->flags & TSF_NEWLINES))            return tt;    }retry:    do {	c = GetChar(ts);        if (c == '\n') {            ts->flags &= ~TSF_DIRTYLINE;            if (ts->flags & TSF_NEWLINES)	        break;        }    } while (JS_ISSPACE(c));    ts->cursor = (ts->cursor + 1) & NTOKENS_MASK;    tp = &CURRENT_TOKEN(ts);    tp->ptr = ts->linebuf.ptr - 1;    tp->pos.begin.index = ts->linepos + (tp->ptr - ts->linebuf.base);    tp->pos.begin.lineno = tp->pos.end.lineno = ts->lineno;    if (c == EOF)	RETURN(TOK_EOF);    if (c != '-' && c != '\n')        ts->flags |= TSF_DIRTYLINE;    hadUnicodeEscape = JS_FALSE;    if (JS_ISIDENT_START(c) ||        (c == '\\' &&         (c = GetUnicodeEscape(ts),          hadUnicodeEscape = JS_ISIDENT_START(c)))) {	INIT_TOKENBUF(&ts->tokenbuf);        for (;;) {	    if (!AddToTokenBuf(cx, &ts->tokenbuf, (jschar)c))		RETURN(TOK_ERROR);	    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);	FINISH_TOKENBUF(&ts->tokenbuf);	atom = js_AtomizeChars(cx,			       ts->tokenbuf.base,			       TOKEN_LENGTH(&ts->tokenbuf),			       0);	if (!atom)	    RETURN(TOK_ERROR);        if (!hadUnicodeEscape && atom->kwindex >= 0) {            struct keyword *kw;            kw = &keywords[atom->kwindex];            tp->t_op = (JSOp) kw->op;            RETURN(kw->tokentype);        }	tp->t_op = JSOP_NAME;	tp->t_atom = atom;	RETURN(TOK_NAME);    }    if (JS7_ISDEC(c) || (c == '.' && JS7_ISDEC(PeekChar(ts)))) {	jsint radix;	const jschar *endptr;	jsdouble dval;	radix = 10;	INIT_TOKENBUF(&ts->tokenbuf);	if (c == '0') {	    if (!AddToTokenBuf(cx, &ts->tokenbuf, (jschar)c))		RETURN(TOK_ERROR);	    c = GetChar(ts);	    if (JS_TOLOWER(c) == 'x') {		if (!AddToTokenBuf(cx, &ts->tokenbuf, (jschar)c))		    RETURN(TOK_ERROR);		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, NULL,                                                     JSREPORT_WARNING,                                                     JSMSG_BAD_OCTAL,                                                     c == '8' ? "08" : "09")) {                        RETURN(TOK_ERROR);                    }		    radix = 10;		}            }	    if (!AddToTokenBuf(cx, &ts->tokenbuf, (jschar)c))		RETURN(TOK_ERROR);	    c = GetChar(ts);	}	if (radix == 10 && (c == '.' || JS_TOLOWER(c) == 'e')) {	    if (c == '.') {		do {		    if (!AddToTokenBuf(cx, &ts->tokenbuf, (jschar)c))			RETURN(TOK_ERROR);		    c = GetChar(ts);		} while (JS7_ISDEC(c));	    }	    if (JS_TOLOWER(c) == 'e') {		if (!AddToTokenBuf(cx, &ts->tokenbuf, (jschar)c))		    RETURN(TOK_ERROR);		c = GetChar(ts);		if (c == '+' || c == '-') {		    if (!AddToTokenBuf(cx, &ts->tokenbuf, (jschar)c))			RETURN(TOK_ERROR);		    c = GetChar(ts);		}		if (!JS7_ISDEC(c)) {		    js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,                                                JSMSG_MISSING_EXPONENT);		    RETURN(TOK_ERROR);		}		do {		    if (!AddToTokenBuf(cx, &ts->tokenbuf, (jschar)c))			RETURN(TOK_ERROR);		    c = GetChar(ts);		} while (JS7_ISDEC(c));	    }	}	UngetChar(ts, c);	FINISH_TOKENBUF(&ts->tokenbuf);	if (radix == 10) {	    if (!js_strtod(cx, ts->tokenbuf.base, &endptr, &dval)) {		js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,                                            JSMSG_OUT_OF_MEMORY);		RETURN(TOK_ERROR);	    }	} else {	    if (!js_strtointeger(cx, ts->tokenbuf.base, &endptr, radix, &dval)) {		js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,                                            JSMSG_OUT_OF_MEMORY);		RETURN(TOK_ERROR);	    }	}	tp->t_dval = dval;	RETURN(TOK_NUMBER);    }    if (c == '"' || c == '\'') {	int32 val, qc = c;	INIT_TOKENBUF(&ts->tokenbuf);	while ((c = GetChar(ts)) != qc) {	    if (c == '\n' || c == EOF) {		UngetChar(ts, c);		js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,                                            JSMSG_UNTERMINATED_STRING);		RETURN(TOK_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') {			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' && JSVERSION_IS_ECMA(cx->version)) {                        /* ECMA follows C by removing escaped newlines. */                        continue;                    }		    break;		}	    }	    if (!AddToTokenBuf(cx, &ts->tokenbuf, (jschar)c))		RETURN(TOK_ERROR);	}	FINISH_TOKENBUF(&ts->tokenbuf);	atom = js_AtomizeChars(cx,			       ts->tokenbuf.base,			       TOKEN_LENGTH(&ts->tokenbuf),			       0);	if (!atom)	    RETURN(TOK_ERROR);	tp->pos.end.lineno = ts->lineno;	tp->t_op = JSOP_STRING;	tp->t_atom = atom;	RETURN(TOK_STRING);    }    switch (c) {      case '\n':         c = TOK_EOL;         break;      case ';': c = TOK_SEMI; break;      case '.': c = TOK_DOT; break;      case '[': c = TOK_LB; break;      case ']': c = TOK_RB; break;      case '{': c = TOK_LC; break;      case '}': c = TOK_RC; break;      case '(': c = TOK_LP; break;      case ')': c = TOK_RP; break;      case ',': c = TOK_COMMA; break;      case '?': c = TOK_HOOK; break;      case ':':        /*         * Default so compiler can modify to JSOP_GETTER if 'p getter: v' in an         * object initializer, likewise for setter.         */        tp->t_op = JSOP_NOP;        c = TOK_COLON;        break;      case '|':	if (MatchChar(ts, c)) {	    c = TOK_OR;	} else if (MatchChar(ts, '=')) {	    tp->t_op = JSOP_BITOR;	    c = TOK_ASSIGN;	} else {	    c = TOK_BITOR;	}	break;      case '^':	if (MatchChar(ts, '=')) {	    tp->t_op = JSOP_BITXOR;	    c = TOK_ASSIGN;	} else {	    c = TOK_BITXOR;	}	break;      case '&':	if (MatchChar(ts, c)) {	    c = TOK_AND;	} else if (MatchChar(ts, '=')) {	    tp->t_op = JSOP_BITAND;	    c = TOK_ASSIGN;	} else {	    c = TOK_BITAND;	}	break;      case '=':	if (MatchChar(ts, c)) {#if JS_HAS_TRIPLE_EQOPS	    tp->t_op = MatchChar(ts, c) ? JSOP_NEW_EQ : (JSOp)cx->jsop_eq;#else	    tp->t_op = cx->jsop_eq;#endif	    c = TOK_EQOP;	} else {	    tp->t_op = JSOP_NOP;	    c = TOK_ASSIGN;	}	break;      case '!':	if (MatchChar(ts, '=')) {#if JS_HAS_TRIPLE_EQOPS	    tp->t_op = MatchChar(ts, '=') ? JSOP_NEW_NE : (JSOp)cx->jsop_ne;#else	    tp->t_op = cx->jsop_ne;#endif	    c = TOK_EQOP;	} else {	    tp->t_op = JSOP_NOT;	    c = TOK_UNARYOP;	}	break;      case '<':	/* NB: treat HTML begin-comment as comment-till-end-of-line */	if (MatchChar(ts, '!')) {	    if (MatchChar(ts, '-')) {		if (MatchChar(ts, '-'))		    goto skipline;		UngetChar(ts, '-');	    }	    UngetChar(ts, '!');	}	if (MatchChar(ts, c)) {	    tp->t_op = JSOP_LSH;	    c = MatchChar(ts, '=') ? TOK_ASSIGN : TOK_SHOP;	} else {	    tp->t_op = MatchChar(ts, '=') ? JSOP_LE : JSOP_LT;	    c = TOK_RELOP;	}	break;      case '>':	if (MatchChar(ts, c)) {	    tp->t_op = MatchChar(ts, c) ? JSOP_URSH : JSOP_RSH;	    c = MatchChar(ts, '=') ? TOK_ASSIGN : TOK_SHOP;	} else {	    tp->t_op = MatchChar(ts, '=') ? JSOP_GE : JSOP_GT;	    c = TOK_RELOP;	}	break;      case '*':	tp->t_op = JSOP_MUL;	c = MatchChar(ts, '=') ? TOK_ASSIGN : TOK_STAR;	break;      case '/':	if (MatchChar(ts, '/')) {skipline:	    while ((c = GetChar(ts)) != EOF && c != '\n')		/* skip to end of line */;	    UngetChar(ts, c);	    goto retry;	}	if (MatchChar(ts, '*')) {	    while ((c = GetChar(ts)) != EOF &&		   !(c == '*' && MatchChar(ts, '/'))) {		if (c == '/' && MatchChar(ts, '*')) {		    if (MatchChar(ts, '/'))			goto retry;		    js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,                                                JSMSG_NESTED_COMMENT);		}	    }	    if (c == EOF) {		js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,                                            JSMSG_UNTERMINATED_COMMENT);		RETURN(TOK_ERROR);	    }	    goto retry;	}#if JS_HAS_REGEXPS	if (ts->flags & TSF_REGEXP) {	    JSObject *obj;	    uintN flags;	    INIT_TOKENBUF(&ts->tokenbuf);	    while ((c = GetChar(ts)) != '/') {		if (c == '\n' || c == EOF) {		    UngetChar(ts, c);		    js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,                                                JSMSG_UNTERMINATED_REGEXP);		    RETURN(TOK_ERROR);		}		if (c == '\\') {		    if (!AddToTokenBuf(cx, &ts->tokenbuf, (jschar)c))			RETURN(TOK_ERROR);		    c = GetChar(ts);		}		if (!AddToTokenBuf(cx, &ts->tokenbuf, (jschar)c))		    RETURN(TOK_ERROR);	    }	    FINISH_TOKENBUF(&ts->tokenbuf);	    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, NULL, JSREPORT_ERROR,                                            JSMSG_BAD_REGEXP_FLAG);		(void) GetChar(ts);		RETURN(TOK_ERROR);	    }	    obj = js_NewRegExpObject(cx, ts,				     ts->tokenbuf.base,				     TOKEN_LENGTH(&ts->tokenbuf),				     flags);            if (!obj)                RETURN(TOK_ERROR);	    atom = js_AtomizeObject(cx, obj, 0);	    if (!atom)		RETURN(TOK_ERROR);	    tp->t_op = JSOP_OBJECT;	    tp->t_atom = atom;	    RETURN(TOK_OBJECT);	}#endif /* JS_HAS_REGEXPS */	tp->t_op = JSOP_DIV;	c = MatchChar(ts, '=') ? TOK_ASSIGN : TOK_DIVOP;	break;      case '%':	tp->t_op = JSOP_MOD;	c = MatchChar(ts, '=') ? TOK_ASSIGN : TOK_DIVOP;	break;      case '~':	tp->t_op = JSOP_BITNOT;	c = TOK_UNARYOP;	break;      case '+':	if (MatchChar(ts, '=')) {	    tp->t_op = JSOP_ADD;	    c = TOK_ASSIGN;	} else if (MatchChar(ts, c)) {	    c = TOK_INC;	} else {	    tp->t_op = JSOP_POS;	    c = TOK_PLUS;	}	break;      case '-':        if (MatchChar(ts, '=')) {            tp->t_op = JSOP_SUB;            c = TOK_ASSIGN;        } else if (MatchChar(ts, c)) {            if (PeekChar(ts) == '>' && !(ts->flags & TSF_DIRTYLINE))                goto skipline;            c = TOK_DEC;        } else {            tp->t_op = JSOP_NEG;            c = TOK_MINUS;        }        ts->flags |= TSF_DIRTYLINE;        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 >= ATOM_INDEX_LIMIT) {		js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,                                            JSMSG_SHARPVAR_TOO_BIG);		RETURN(TOK_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_ReportErrorFlagsAndNumber(cx,                                              JSREPORT_WARNING |                                              JSREPORT_STRICT,                                              js_GetErrorMessage, NULL,                                              JSMSG_DEPRECATED_USAGE,                                              buf)) {                RETURN(TOK_ERROR);            }        }	if (c == '=')	    RETURN(TOK_DEFSHARP);	if (c == '#')	    RETURN(TOK_USESHARP);	goto badchar;      }      badchar:#endif /* JS_HAS_SHARP_VARS */      default:	js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,                                    JSMSG_ILLEGAL_CHARACTER);	RETURN(TOK_ERROR);    }    JS_ASSERT(c < TOK_LIMIT);    RETURN((JSTokenType)c);#undef INIT_TOKENBUF#undef FINISH_TOKENBUF#undef TOKEN_LENGTH#undef RETURN}