Ejemplo n.º 1
0
static int scanchar(Rboolean inQuote, LocalData *d)
{
    int next;
    if (d->save) {
	next = d->save;
	d->save = 0;
    } else
	next = scanchar_raw(d);
    if(next == d->comchar && !inQuote) {
	do
	    next = scanchar_raw(d);
	while (next != '\n' && next != R_EOF);
    }
    if(next == '\\' && d->escapes) {
	next = scanchar_raw(d);
	if ('0' <= next && next <= '8') {
	    int octal = next - '0';
	    if ('0' <= (next = scanchar_raw(d)) && next <= '8') {
		octal = 8 * octal + next - '0';
		if ('0' <= (next = scanchar_raw(d)) && next <= '8') {
		    octal = 8 * octal + next - '0';
		} else unscanchar(next, d);
	    } else unscanchar(next, d);
	    next = octal;
	} else
	    switch(next) {
	    case 'a': next = '\a'; break;
	    case 'b': next = '\b'; break;
	    case 'f': next = '\f'; break;
	    case 'n': next = '\n'; break;
	    case 'r': next = '\r'; break;
	    case 't': next = '\t'; break;
	    case 'v': next = '\v'; break;
	    case 'x': {
		int val = 0; int i, ext;
		for(i = 0; i < 2; i++) {
		    next = scanchar_raw(d);
		    if(next >= '0' && next <= '9') ext = next - '0';
		    else if (next >= 'A' && next <= 'F') ext = next - 'A' + 10;
		    else if (next >= 'a' && next <= 'f') ext = next - 'a' + 10;
		    else {unscanchar(next, d); break;}
		    val = 16*val + ext;
		}
		next = val;
	    }
		break;
	    default:
		/* Any other char and even EOF escapes to itself, but we
		   need to preserve \" etc inside quotes.
		 */
		if(inQuote && strchr(d->quoteset, next)) {
		    unscanchar(next, d);
		    next = '\\';
		}
		break;
	    }
    }
    return next;
}
Ejemplo n.º 2
0
static int trim_leading(const char **str) {
	int ch;

	do {
		ch = scanchar(str);
		/*when break*/
		if (ch == EOF)
			break;
	} while (is_space(ch));

	unscanchar(str, ch);
	return ch;
}
Ejemplo n.º 3
0
static int
yyGetNumber(int ch)
{
    int isFloat = 0;
    char buf[1024];
    int nInBuf = 0;

    buf[0] = ch;
    nInBuf = 1;
    while (((ch = scanchar()) != EOF)
           && (isxdigit(ch) || ((nInBuf == 1) && (ch == 'x'))))
    {
        buf[nInBuf++] = ch;
    }
    if (ch == '.')
    {
        isFloat = 1;
        buf[nInBuf++] = ch;
        while (((ch = scanchar()) != EOF) && (isxdigit(ch)))
        {
            buf[nInBuf++] = ch;
        }
    }
    buf[nInBuf++] = '\0';
    if ((ch != EOF) && (!isspace(ch)))
        unscanchar(ch);

    if (isFloat)
    {
        float tmp;
        if (sscanf(buf, "%g", &tmp) == 1)
        {
            scanInt = tmp * XkbGeomPtsPerMM;
            return FLOAT;
        }
    }
    else if (sscanf(buf, "%i", &scanInt) == 1)
        return INTEGER;
    fprintf(stderr, "Malformed number %s\n", buf);
    return ERROR_TOK;
}
Ejemplo n.º 4
0
static int
yyGetIdent(int first)
{
    int ch, i, j, found;
    int rtrn = IDENT;

    scanBuf[0] = first;
    j = 1;
    while (((ch = scanchar()) != EOF) && (isalnum(ch) || (ch == '_')))
    {
        if (j < sizeof(scanBuf) - 1)
            scanBuf[j++] = ch;
    }
    scanBuf[j++] = '\0';
    found = 0;

    for (i = 0; (!found) && (i < numKeywords); i++)
    {
        if (uStrCaseCmp(scanBuf, keywords[i].keyword) == 0)
        {
            rtrn = keywords[i].token;
            found = 1;
        }
    }
    if (!found)
    {
        scanStrLine = lineNum;
        rtrn = IDENT;
    }

    if ((ch != EOF) && (!isspace(ch)))
        unscanchar(ch);
    else if (ch == '\n')
        lineNum++;

    return rtrn;
}
Ejemplo n.º 5
0
static int scan_int(const char **in, int base, int width, int *res) {
	int neg = 0;
	int dst = 0;
	int ch;
	int i;
	int not_empty = 0;

	if (EOF == (ch = trim_leading(in))) {
		return EOF;
	}

	if ((ch == '-') || (ch == '+')) {
		neg = (ch == '-');
		scanchar(in);
	} else {
		dst = 0;
	}

	for (i = 0; (ch = (int) scanchar(in)) != EOF; i++) {
		if (!(base == 10 ? isdigit(ch) : isxdigit(ch)) || (0 == width)) {
			unscanchar(in, ch);
			/*end conversion*/
			break;
		}
		not_empty = 1;
		dst = base * dst + ch_to_digit(ch, base);
	}

	if (!not_empty) {
		return -1;
	}

	if (neg)
		dst = -dst;
	*res = dst;
	return 0;
}
Ejemplo n.º 6
0
int
yylex(void)
{
    int ch;
    int rtrn;

    do
    {
        ch = scanchar();
        if (ch == '\n')
        {
            lineNum++;
        }
        else if (ch == '#')
        {                       /* handle shell style '#' comments */
            do
            {
                ch = scanchar();
            }
            while ((ch != '\n') && (ch != EOF));
            lineNum++;
        }
        else if (ch == '/')
        {                       /* handle C++ style double-/ comments */
            int newch = scanchar();
            if (newch == '/')
            {
                do
                {
                    ch = scanchar();
                }
                while ((ch != '\n') && (ch != EOF));
                lineNum++;
            }
            else if (newch != EOF)
            {
                unscanchar(newch);
            }
        }
    }
    while ((ch != EOF) && (isspace(ch)));
    if (ch == '=')
        rtrn = EQUALS;
    else if (ch == '+')
        rtrn = PLUS;
    else if (ch == '-')
        rtrn = MINUS;
    else if (ch == '/')
        rtrn = DIVIDE;
    else if (ch == '*')
        rtrn = TIMES;
    else if (ch == '{')
        rtrn = OBRACE;
    else if (ch == '}')
        rtrn = CBRACE;
    else if (ch == '(')
        rtrn = OPAREN;
    else if (ch == ')')
        rtrn = CPAREN;
    else if (ch == '[')
        rtrn = OBRACKET;
    else if (ch == ']')
        rtrn = CBRACKET;
    else if (ch == '.')
        rtrn = DOT;
    else if (ch == ',')
        rtrn = COMMA;
    else if (ch == ';')
        rtrn = SEMI;
    else if (ch == '!')
        rtrn = EXCLAM;
    else if (ch == '~')
        rtrn = INVERT;
    else if (ch == '"')
        rtrn = yyGetString();
    else if (ch == '<')
        rtrn = yyGetKeyName();
    else if (isalpha(ch) || (ch == '_'))
        rtrn = yyGetIdent(ch);
    else if (isdigit(ch))
        rtrn = yyGetNumber(ch);
    else if (ch == EOF)
        rtrn = END_OF_FILE;
    else
    {
#ifdef DEBUG
        if (debugFlags)
            fprintf(stderr,
                    "Unexpected character %c (%d) in input stream\n", ch, ch);
#endif
        rtrn = ERROR_TOK;
    }
#ifdef DEBUG
    if (debugFlags & 0x2)
        fprintf(stderr, "scan: %s\n", tokText(rtrn));
#endif
    return rtrn;
}
Ejemplo n.º 7
0
static int
yyGetKeyName(void)
{
    int ch, i;

    i = 0;
    while (((ch = scanchar()) != EOF) && (ch != '>'))
    {
        if (ch == '\\')
        {
            if ((ch = scanchar()) != EOF)
            {
                if (ch == 'n')
                    ch = '\n';
                else if (ch == 't')
                    ch = '\t';
                else if (ch == 'v')
                    ch = '\v';
                else if (ch == 'b')
                    ch = '\b';
                else if (ch == 'r')
                    ch = '\r';
                else if (ch == 'f')
                    ch = '\f';
                else if (ch == 'e')
                    ch = '\033';
                else if (ch == '0')
                {
                    int tmp, stop;
                    ch = stop = 0;
                    if (((tmp = scanchar()) != EOF) && (isdigit(tmp))
                        && (tmp != '8') && (tmp != '9'))
                    {
                        ch = (ch * 8) + (tmp - '0');
                    }
                    else
                    {
                        stop = 1;
                        unscanchar(tmp);
                    }
                    if ((!stop) && ((tmp = scanchar()) != EOF)
                        && (isdigit(tmp)) && (tmp != '8') && (tmp != '9'))
                    {
                        ch = (ch * 8) + (tmp - '0');
                    }
                    else
                    {
                        stop = 1;
                        unscanchar(tmp);
                    }
                    if ((!stop) && ((tmp = scanchar()) != EOF)
                        && (isdigit(tmp)) && (tmp != '8') && (tmp != '9'))
                    {
                        ch = (ch * 8) + (tmp - '0');
                    }
                    else
                    {
                        stop = 1;
                        unscanchar(tmp);
                    }
                }
            }
            else
                return ERROR_TOK;
        }

        if (i < sizeof(scanBuf) - 1)
            scanBuf[i++] = ch;
    }
    if ((ch == '>') && (i < 5))
    {
        scanBuf[i++] = '\0';
        scanStrLine = lineNum;
        return KEYNAME;
    }
    return ERROR_TOK;
}
Ejemplo n.º 8
0
SEXP readtablehead(SEXP args)
{
    SEXP file, comstr, ans = R_NilValue, ans2, quotes, sep;
    int nlines, i, c, quote=0, nread, nbuf, buf_size = BUF_SIZE, blskip;
    const char *p; char *buf;
    Rboolean empty, skip;
    LocalData data = {NULL, 0, 0, '.', NULL, NO_COMCHAR, 0, NULL, FALSE,
		      FALSE, 0, FALSE, FALSE};
    data.NAstrings = R_NilValue;

    args = CDR(args);

    file = CAR(args);		   args = CDR(args);
    nlines = asInteger(CAR(args)); args = CDR(args);
    comstr = CAR(args);		   args = CDR(args);
    blskip = asLogical(CAR(args)); args = CDR(args);
    quotes = CAR(args);		   args = CDR(args);
    sep = CAR(args);

    if (nlines <= 0 || nlines == NA_INTEGER)
	error(_("invalid '%s' argument"), "nlines");
    if (blskip == NA_LOGICAL) blskip = 1;
    if (isString(quotes)) {
	const char *sc = translateChar(STRING_ELT(quotes, 0));
	if (strlen(sc)) data.quoteset = strdup(sc);
	else data.quoteset = "";
    } else if (isNull(quotes))
	data.quoteset = "";
    else
	error(_("invalid quote symbol set"));

    if (TYPEOF(comstr) != STRSXP || length(comstr) != 1)
	error(_("invalid '%s' argument"), "comment.char");
    p = translateChar(STRING_ELT(comstr, 0));
    data.comchar = NO_COMCHAR; /*  here for -Wall */
    if (strlen(p) > 1)
	error(_("invalid '%s' argument"), "comment.char");
    else if (strlen(p) == 1) data.comchar = (int)*p;
    if (isString(sep) || isNull(sep)) {
	if (length(sep) == 0) data.sepchar = 0;
	else data.sepchar = (unsigned char) translateChar(STRING_ELT(sep, 0))[0];
	/* gets compared to chars: bug prior to 1.7.0 */
    } else error(_("invalid '%s' argument"), "sep");

    i = asInteger(file);
    data.con = getConnection(i);
    data.ttyflag = (i == 0);
    data.wasopen = data.con->isopen;
    if(!data.wasopen) {
	strcpy(data.con->mode, "r");
	if(!data.con->open(data.con)) error(_("cannot open the connection"));
    } else { /* for a non-blocking connection, more input may
		have become available, so re-position */
	if(data.con->canseek && !data.con->blocking)
	    data.con->seek(data.con, data.con->seek(data.con, -1, 1, 1), 1, 1);
    }

    buf = (char *) malloc(buf_size);
    if(!buf)
	error(_("cannot allocate buffer in 'readTableHead'"));

    PROTECT(ans = allocVector(STRSXP, nlines));
    for(nread = 0; nread < nlines; ) {
	nbuf = 0; empty = TRUE, skip = FALSE;
	if (data.ttyflag) sprintf(ConsolePrompt, "%d: ", nread);
	/* want to interpret comments here, not in scanchar */
	while((c = scanchar(TRUE, &data)) != R_EOF) {
	    if(nbuf >= buf_size -1) {
		buf_size *= 2;
		char *tmp = (char *) realloc(buf, buf_size);
		if(!tmp) {
		    free(buf);
		    error(_("cannot allocate buffer in 'readTableHead'"));
		} else buf = tmp;
	    }
	    /* Need to handle escaped embedded quotes, and how they are
	       escaped depends on 'sep' */
	    if(quote) {
		if(data.sepchar == 0 && c == '\\') {
		    /* all escapes should be passed through */
		    buf[nbuf++] = (char) c;
		    c = scanchar(TRUE, &data);
		    if(c == R_EOF)
			error(_("\\ followed by EOF"));
		    buf[nbuf++] = (char) c;
		    continue;
		} else if(quote && c == quote) {
		    if(data.sepchar == 0)
			quote = 0;
		    else { /* need to check for doubled quote */
			char c2 = (char) scanchar(TRUE, &data);
			if(c2 == quote)
			    buf[nbuf++] = (char) c; /* and c = c2 */
			else {
			    unscanchar(c2, &data);
			    quote = 0;
			}
		    }
		}
	    } else if(!quote && !skip && strchr(data.quoteset, c)) quote = c;
	    /* A line is empty only if it contains nothing before
	       EOL, EOF or a comment char.
	       A line containing just white space is not empty if sep=","
	       However foo\nEOF does not have a final empty line.
	    */
	    if(empty && !skip)
		if(c != '\n' && c != data.comchar) empty = FALSE;
	    if(!quote && !skip && c == data.comchar) skip = TRUE;
	    if(quote || c != '\n') buf[nbuf++] = (char) c; else break;
	}
	buf[nbuf] = '\0';
	if(data.ttyflag && empty) goto no_more_lines;
	if(!empty || (c != R_EOF && !blskip)) { /* see previous comment */
	    SET_STRING_ELT(ans, nread, mkChar(buf));
	    nread++;
	}
	if(c == R_EOF) goto no_more_lines;
    }
    UNPROTECT(1);
    free(buf);
    if(!data.wasopen) data.con->close(data.con);
    if (data.quoteset[0]) free(data.quoteset);
    return ans;

no_more_lines:
    if(!data.wasopen) data.con->close(data.con);
    if(nbuf > 0) { /* incomplete last line */
	if(data.con->text && data.con->blocking) {
	    warning(_("incomplete final line found by readTableHeader on '%s'"),
		    data.con->description);
	} else
	    error(_("incomplete final line found by readTableHeader on '%s'"),
		  data.con->description);
    }
    free(buf);
    PROTECT(ans2 = allocVector(STRSXP, nread));
    for(i = 0; i < nread; i++)
	SET_STRING_ELT(ans2, i, STRING_ELT(ans, i));
    UNPROTECT(2);
    if (data.quoteset[0]) free(data.quoteset);
    return ans2;
}
Ejemplo n.º 9
0
SEXP countfields(SEXP args)
{
    SEXP ans, file, sep,  bns, quotes, comstr;
    int nfields, nskip, i, c, inquote, quote = 0;
    int blocksize, nlines, blskip;
    const char *p;
    Rboolean dbcslocale = (MB_CUR_MAX == 2);
    LocalData data = {NULL, 0, 0, '.', NULL, NO_COMCHAR, 0, NULL, FALSE,
		      FALSE, 0, FALSE, FALSE};
    data.NAstrings = R_NilValue;

    args = CDR(args);

    file = CAR(args);	args = CDR(args);
    sep = CAR(args);	args = CDR(args);
    quotes = CAR(args);	 args = CDR(args);
    nskip = asInteger(CAR(args));  args = CDR(args);
    blskip = asLogical(CAR(args)); args = CDR(args);
    comstr = CAR(args);
    if (TYPEOF(comstr) != STRSXP || length(comstr) != 1)
	error(_("invalid '%s' argument"), "comment.char");
    p = translateChar(STRING_ELT(comstr, 0));
    data.comchar = NO_COMCHAR; /*  here for -Wall */
    if (strlen(p) > 1)
	error(_("invalid '%s' argument"), "comment.char");
    else if (strlen(p) == 1) data.comchar = (unsigned char)*p;

    if (nskip < 0 || nskip == NA_INTEGER) nskip = 0;
    if (blskip == NA_LOGICAL) blskip = 1;

    if (isString(sep) || isNull(sep)) {
	if (length(sep) == 0) data.sepchar = 0;
	else data.sepchar = (unsigned char) translateChar(STRING_ELT(sep, 0))[0];
	/* gets compared to chars: bug prior to 1.7.0 */
    } else error(_("invalid '%s' argument"), "sep");

    if (isString(quotes)) {
	const char *sc = translateChar(STRING_ELT(quotes, 0));
	if (strlen(sc)) data.quoteset = strdup(sc);
	else data.quoteset = "";
    } else if (isNull(quotes))
	data.quoteset = "";
    else
	error(_("invalid quote symbol set"));

    i = asInteger(file);
    data.con = getConnection(i);
    if(i == 0) {
	data.ttyflag = 1;
    } else {
	data.ttyflag = 0;
	data.wasopen = data.con->isopen;
	if(!data.wasopen) {
	    strcpy(data.con->mode, "r");
	    if(!data.con->open(data.con))
		error(_("cannot open the connection"));
	    if(!data.con->canread) {
		data.con->close(data.con);
		error(_("cannot read from this connection"));
	    } 
	} else {
	    if(!data.con->canread) 
		error(_("cannot read from this connection"));
	}
	for (i = 0; i < nskip; i++) /* MBCS-safe */
	    while ((c = scanchar(FALSE, &data)) != '\n' && c != R_EOF);
    }

    blocksize = SCAN_BLOCKSIZE;
    PROTECT(ans = allocVector(INTSXP, blocksize));
    nlines = 0;
    nfields = 0;
    inquote = 0;

    data.save = 0;

    for (;;) {
	c = scanchar(inquote, &data);
	if (c == R_EOF)	 {
	    if (nfields != 0)
		INTEGER(ans)[nlines] = nfields;
	    else nlines--;
	    goto donecf;
	}
	else if (c == '\n') {
	    if (nfields || !blskip) {
		INTEGER(ans)[nlines] = nfields;
		nlines++;
		nfields = 0;
		inquote = 0;
	    }
	    if (nlines == blocksize) {
		bns = ans;
		blocksize = 2 * blocksize;
		ans = allocVector(INTSXP, blocksize);
		UNPROTECT(1);
		PROTECT(ans);
		copyVector(ans, bns);
	    }
	    continue;
	}
	else if (data.sepchar) {
	    if (nfields == 0)
		nfields++;
	    if (inquote && (c == R_EOF || c == '\n')) {
		if(!data.wasopen) data.con->close(data.con);
		error(_("string terminated by newline or EOF"));
	    }
	    if (inquote && c == quote)
		inquote = 0;
	    else if (strchr(data.quoteset, c)) {
		inquote = 1;
		quote = c;
	    }
	    if (c == data.sepchar && !inquote)
		nfields++;
	}
	else if (!Rspace(c)) {
	    if (strchr(data.quoteset, c)) {
		quote = c;
		inquote = 1;
		while ((c = scanchar(inquote, &data)) != quote) {
		    if (c == R_EOF || c == '\n') {
			if(!data.wasopen) data.con->close(data.con);
			error(_("string terminated by newline or EOF"));
		    }
		}
		inquote = 0;
	    } else {
		do {
		    if(dbcslocale && btowc(c) == WEOF) scanchar2(&data);
		    c = scanchar(FALSE, &data);
		} while (!Rspace(c) && c != R_EOF);
		if (c == R_EOF) c = '\n';
		unscanchar(c, &data);
	    }
	    nfields++;
	}

    }
 donecf:
    /* we might have a character that was unscanchar-ed.
       So pushback if possible */
    if (data.save && !data.ttyflag && data.wasopen) {
	char line[2] = " ";
	line[0] = (char) data.save;
	con_pushback(data.con, FALSE, line);
    }
    if(!data.wasopen) data.con->close(data.con);

    if (nlines < 0) {
	UNPROTECT(1);
	return R_NilValue;
    }
    if (nlines == blocksize) {
	UNPROTECT(1);
	return ans;
    }

    bns = allocVector(INTSXP, nlines+1);
    for (i = 0; i <= nlines; i++)
	INTEGER(bns)[i] = INTEGER(ans)[i];
    UNPROTECT(1);
    if (data.quoteset[0]) free(data.quoteset);
    return bns;
}
Ejemplo n.º 10
0
/*XX  Can we pass this routine an R_StringBuffer? appears so.
   But do we have to worry about continuation lines and whatever
   is currently in the buffer before we call this? In other words,
   what if this appends to the existing content. Appears it writes in
   directly at position 0.
 */
static char *
fillBuffer(SEXPTYPE type, int strip, int *bch, LocalData *d,
	   R_StringBuffer *buffer)
{
/* The basic reader function, called from scanVector() and scanFrame().
   Reads into _buffer_	which later will be read out by extractItem().

   bch is used to distinguish \r, \n and EOF from more input available.
*/
    char *bufp;
    int c, quote, filled, nbuf = MAXELTSIZE, m, mm = 0;
    Rboolean dbcslocale = (MB_CUR_MAX == 2);

    m = 0;
    filled = 1;
    if (d->sepchar == 0) {
	/* skip all space or tabs: only look at lead bytes here */
	strip = 0; /* documented to be ignored in this case */
	while ((c = scanchar(FALSE, d)) == ' ' || c == '\t') ;
	if (c == '\n' || c == '\r' || c == R_EOF) {
	    filled = c;
	    goto donefill;
	}
	if ((type == STRSXP || type == NILSXP) && strchr(d->quoteset, c)) {
	    quote = c;
	    while ((c = scanchar(TRUE, d)) != R_EOF && c != quote) {
		if (m >= nbuf - 3) {
		    nbuf *= 2;
		    R_AllocStringBuffer(nbuf, buffer);
		}
		if (c == '\\') {
		    /* If this is an embedded quote, unquote it, but
		       otherwise keep backslashes */
		    c = scanchar(TRUE, d);
		    if (c == R_EOF) break;
		    if(c != quote) buffer->data[m++] = '\\';
		}
		buffer->data[m++] = (char) c;
		if(dbcslocale && btowc(c) == WEOF)
		    buffer->data[m++] = (char) scanchar2(d);
	    }
	    if (c == R_EOF)
		warning(_("EOF within quoted string"));
	    c = scanchar(FALSE, d);
	    mm = m;
	}
	else { /* not a quoted char string */
	    do {
		if (m >= nbuf - 3) {
		    nbuf *= 2;
		    R_AllocStringBuffer(nbuf, buffer);
		}
		buffer->data[m++] = (char) c;
		if(dbcslocale && btowc(c) == WEOF)
		    buffer->data[m++] = (char) scanchar2(d);
		c = scanchar(FALSE, d);
	    } while (!Rspace(c) && c != R_EOF);
	}
	/* skip all space or tabs: only look at lead bytes here */
	while (c == ' ' || c == '\t') c = scanchar(FALSE, d);
	if (c == '\n' || c == '\r' || c == R_EOF)
	    filled = c;
	else
	    unscanchar(c, d);
    }
    else { /* have separator */
	while ((c = scanchar(FALSE, d)) != d->sepchar &&
	       c != '\n' && c != '\r' && c != R_EOF)
	    {
		/* eat white space */
		if (type != STRSXP)
		    while (c == ' ' || c == '\t')
			if ((c = scanchar(FALSE, d)) == d->sepchar
			    || c == '\n' || c == '\r' || c == R_EOF) {
			    filled = c;
			    goto donefill;
			}
		/* CSV style quoted string handling */
		if ((type == STRSXP || type == NILSXP)
		    && c != 0 && strchr(d->quoteset, c)) {
		    quote = c;
		inquote:
		    while ((c = scanchar(TRUE, d)) != R_EOF && c != quote) {
			if (m >= nbuf - 3) {
			    nbuf *= 2;
			    R_AllocStringBuffer(nbuf, buffer);
			}
			buffer->data[m++] = (char) c;
			if(dbcslocale && btowc(c) == WEOF)
			    buffer->data[m++] = (char) scanchar2(d);
		    }
		    if (c == R_EOF)
			warning(_("EOF within quoted string"));
		    c = scanchar(TRUE, d); /* only peek at lead byte
					      unless ASCII */
		    if (c == quote) {
			if (m >= nbuf - 3) {
			    nbuf *= 2;
			    R_AllocStringBuffer(nbuf, buffer);
			}
			buffer->data[m++] = (char) quote;
			goto inquote; /* FIXME: Ick! Clean up logic */
		    }
		    mm = m;
		    if (c == d->sepchar || c == '\n' || c == '\r' || c == R_EOF){
			filled = c;
			goto donefill;
		    }
		    else {
			unscanchar(c, d);
			continue;
		    }
		} /* end of CSV-style quote handling */
		if (!strip || m > 0 || !Rspace(c)) { /* only lead byte */
		    if (m >= nbuf - 3) {
			nbuf *= 2;
			R_AllocStringBuffer(nbuf, buffer);
		    }
		    buffer->data[m++] = (char) c;
		    if(dbcslocale && btowc(c) == WEOF)
			buffer->data[m++] = (char) scanchar2(d);
		}
	    }
	filled = c; /* last lead byte in a DBCS */
    }
 donefill:
    /* strip trailing white space, if desired and if item is non-null */
    bufp = &buffer->data[m];
    if (strip && m > mm) {
	do {c = (int)*--bufp;} while(m-- > mm && Rspace(c));
	bufp++;
    }
    *bufp = '\0';
    /* Remove UTF-8 BOM */
    if(d->atStart && utf8locale &&
       !memcmp(buffer->data, "\xef\xbb\xbf", 3))
	memmove(buffer->data, buffer->data+3, strlen(buffer->data) + 1);
    d->atStart = FALSE;
    *bch = filled;
    return buffer->data;
}