ts->flags |= TSF_CRFLAG;
ts->flags |= TSF_CRFLAG;  if (len == 0) {  return GetChar(ts); }
GetChar(JSTokenStream *ts){    int32 c;    ptrdiff_t len, olen;    jschar *nl;    if (ts->ungetpos != 0) {	c = ts->ungetbuf[--ts->ungetpos];    } else {	if (ts->linebuf.ptr == ts->linebuf.limit) {	    len = PTRDIFF(ts->userbuf.limit, ts->userbuf.ptr, jschar);	    if (len <= 0) {		/* Fill ts->userbuf so that \r and \r\n convert to \n. */		if (ts->file) {		    JSBool crflag;		    char cbuf[JS_LINE_LIMIT];		    jschar *ubuf;		    ptrdiff_t i, j;		    crflag = (ts->flags & TSF_CRFLAG) != 0;		    if (!fgets(cbuf, JS_LINE_LIMIT - crflag, ts->file)) {			ts->flags |= TSF_EOF;			return EOF;		    }		    len = olen = strlen(cbuf);		    JS_ASSERT(len > 0);		    ubuf = ts->userbuf.base;		    i = 0;		    if (crflag) {			ts->flags &= ~TSF_CRFLAG;			if (cbuf[0] != '\n') {			    ubuf[i++] = '\n';			    len++;			    ts->linepos--;			}		    }		    for (j = 0; i < len; i++, j++)			ubuf[i] = (jschar) (unsigned char) cbuf[j];		    ts->userbuf.limit = ubuf + len;		    ts->userbuf.ptr = ubuf;		} else {		    ts->flags |= TSF_EOF;		    return EOF;		}	    }            if (ts->listener)                (*ts->listener)(ts->filename, ts->lineno, ts->userbuf.ptr, len,                                &ts->listenerTSData, ts->listenerData);	    /*	     * Any one of \n, \r, or \r\n ends a line (longest match wins).	     */	    for (nl = ts->userbuf.ptr; nl < ts->userbuf.limit; nl++) {		if (*nl == '\n')		    break;		if (*nl == '\r') {		    if (nl + 1 < ts->userbuf.limit && nl[1] == '\n')			nl++;		    break;		}	    }	    /*	     * If there was a line terminator, copy thru it into linebuf.	     * Else copy JS_LINE_LIMIT-1 bytes into linebuf.	     */	    if (nl < ts->userbuf.limit)		len = PTRDIFF(nl, ts->userbuf.ptr, jschar) + 1;	    if (len >= JS_LINE_LIMIT)		len = JS_LINE_LIMIT - 1;	    js_strncpy(ts->linebuf.base, ts->userbuf.ptr, len);	    ts->userbuf.ptr += len;	    olen = len;	    /*	     * Make sure linebuf contains \n for EOL (don't do this in	     * userbuf because the user's string might be readonly).	     */	    if (nl < ts->userbuf.limit) {		if (*nl == '\r') {		    if (ts->linebuf.base[len-1] == '\r') {                        /*                         * Does the line segment end in \r?  We must check for                         * a \n at the front of the next segment before storing                         * a \n into linebuf.  This case only applies when                         * reading from a file.                         */			if (nl + 1 == ts->userbuf.limit) {			    len--;			    ts->flags |= TSF_CRFLAG;			} else                            ts->linebuf.base[len-1] = '\n';		    }		} else if (*nl == '\n') {		    if (nl > ts->userbuf.base &&			nl[-1] == '\r' &&			ts->linebuf.base[len-2] == '\r') {			len--;			JS_ASSERT(ts->linebuf.base[len] == '\n');			ts->linebuf.base[len-1] = '\n';		    }		}	    }	    /* Reset linebuf based on adjusted segment length. */	    ts->linebuf.limit = ts->linebuf.base + len;	    ts->linebuf.ptr = ts->linebuf.base;	    /* Update position of linebuf within physical line in userbuf. */	    if (!(ts->flags & TSF_NLFLAG))		ts->linepos += ts->linelen;	    else		ts->linepos = 0;	    if (ts->linebuf.limit[-1] == '\n')		ts->flags |= TSF_NLFLAG;	    else		ts->flags &= ~TSF_NLFLAG;	    /* Update linelen from original segment length. */	    ts->linelen = olen;	}	c = *ts->linebuf.ptr++;    }    if (c == '\n')	ts->lineno++;    return c;}