/* Generated by re2c */
// re2c $INPUT -o $OUTPUT --recursive-functions -i
#include <assert.h>
#include <stdio.h>
#include <string.h>

#define YYMAXFILL 1

#define SIZE 4096

typedef struct {
    FILE *file;
    char buf[SIZE + YYMAXFILL], *lim, *cur, *mar, *tok;
    int eof;
} Input;

static int fill(Input *in, size_t need)
{
    if (in->eof) {
        return 1;
    }
    const size_t free = in->tok - in->buf;
    if (free < need) {
        return 2;
    }
    memmove(in->buf, in->tok, in->lim - in->tok);
    in->lim -= free;
    in->cur -= free;
    in->mar -= free;
    in->tok -= free;
    in->lim += fread(in->lim, 1, free, in->file);
    if (in->lim < in->buf + SIZE) {
        in->eof = 1;
        memset(in->lim, 0, YYMAXFILL);
        in->lim += YYMAXFILL;
    }
    return 0;
}

static void init(Input *in, FILE *file)
{
    in->file = file;
    in->cur = in->mar = in->tok = in->lim = in->buf + SIZE;
    in->eof = 0;
    fill(in, 1);
}

static int lex_loop(Input *in, int count);


static int yy0(Input* in, int count);
static int yy1(Input* in, int count);
static int yy2(Input* in, int count);
static int yy3(Input* in, int count);
static int yy4(Input* in, int count);
static int yy5(Input* in, int count);
static int yy6(Input* in, int count);
static int yy7(Input* in, int count);
static int lex(Input* in, int count);

static int yy0(Input* in, int count) {
	if (in->lim <= in->cur) if (fill(in, 1) != 0) return -1;
	char yych = *in->cur++;
	switch (yych) {
		case 0x00: return yy1(in, count);
		case ' ': return yy3(in, count);
		case '\'': return yy5(in, count);
		default: return yy2(in, count);
	}
}

static int yy1(Input* in, int count) {
	return (in->lim - in->cur == YYMAXFILL - 1) ? count : -1;
}

static int yy2(Input* in, int count) {
	return -1;
}

static int yy3(Input* in, int count) {
	if (in->lim <= in->cur) if (fill(in, 1) != 0) return -1;
	char yych = *in->cur;
	switch (yych) {
		case ' ':
			++in->cur;
			return yy3(in, count);
		default: return yy4(in, count);
	}
}

static int yy4(Input* in, int count) {
	return lex_loop(in, count);
}

static int yy5(Input* in, int count) {
	if (in->lim <= in->cur) if (fill(in, 1) != 0) return -1;
	char yych = *in->cur++;
	switch (yych) {
		case '\'': return yy6(in, count);
		case '\\': return yy7(in, count);
		default: return yy5(in, count);
	}
}

static int yy6(Input* in, int count) {
	return lex_loop(in, ++count);
}

static int yy7(Input* in, int count) {
	if (in->lim <= in->cur) if (fill(in, 1) != 0) return -1;
	++in->cur;
	return yy5(in, count);
}

static int lex(Input* in, int count) {
	return yy0(in, count);
}



static int lex_loop(Input *in, int count)
{;
    in->tok = in->cur;
    return lex(in, count);
}

int main()
{
    const char *fname = "input";
    const char str[] = "'qu\0tes' 'are' 'fine: \\'' ";
    FILE *f;
    Input in;

    // prepare input file: a few times the size of the buffer,
    // containing strings with zeroes and escaped quotes
    f = fopen(fname, "w");
    for (int i = 0; i < SIZE; ++i) {
        fwrite(str, 1, sizeof(str) - 1, f);
    }
    fclose(f);

    f = fopen(fname, "r");
    init(&in, f);
    assert(lex_loop(&in, 0) == SIZE * 3);
    fclose(f);

    remove(fname);
    return 0;
}
