/* Generated by re2c */ #line 1 "c/state/push.re" // re2c $INPUT -o $OUTPUT -f #include <assert.h> #include <stdio.h> #include <string.h> #define DEBUG 0 #define LOG(...) if (DEBUG) fprintf(stderr, __VA_ARGS__); #define BUFSIZE 10 typedef struct { FILE *file; char buf[BUFSIZE + 1], *lim, *cur, *mar, *tok; unsigned yyaccept; int state; } Input; static void init(Input *in, FILE *f) { in->file = f; in->cur = in->mar = in->tok = in->lim = in->buf + BUFSIZE; in->lim[0] = 0; // append sentinel symbol in->yyaccept = 0; in->state = -1; } typedef enum {END, READY, WAITING, BAD_PACKET, BIG_PACKET} Status; static Status fill(Input *in) { const size_t shift = in->tok - in->buf; const size_t free = BUFSIZE - (in->lim - in->tok); if (free < 1) return BIG_PACKET; memmove(in->buf, in->tok, BUFSIZE - shift); in->lim -= shift; in->cur -= shift; in->mar -= shift; in->tok -= shift; const size_t read = fread(in->lim, 1, free, in->file); in->lim += read; in->lim[0] = 0; // append sentinel symbol return READY; } static Status lex(Input *in, unsigned int *recv) { char yych; switch (in->state) { default: goto yy0; case 0: if (in->lim <= in->cur) goto yyeof1; goto yyFillLabel0; case 1: if (in->lim <= in->cur) goto yy4; goto yyFillLabel1; case 2: if (in->lim <= in->cur) goto yy10; goto yyFillLabel2; } loop: in->tok = in->cur; #line 71 "c/state/push.c" yy0: yyFillLabel0: yych = *in->cur; switch (yych) { case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': goto yy5; default: if (in->lim <= in->cur) { in->state = 0; return WAITING; } goto yy3; } yy3: ++in->cur; yy4: #line 67 "c/state/push.re" { return BAD_PACKET; } #line 115 "c/state/push.c" yy5: in->mar = ++in->cur; yyFillLabel1: yych = *in->cur; switch (yych) { case ';': goto yy6; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': goto yy8; default: if (in->lim <= in->cur) { in->state = 1; return WAITING; } goto yy4; } yy6: ++in->cur; #line 69 "c/state/push.re" { *recv = *recv + 1; goto loop; } #line 159 "c/state/push.c" yy8: ++in->cur; yyFillLabel2: yych = *in->cur; switch (yych) { case ';': goto yy6; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': goto yy8; default: if (in->lim <= in->cur) { in->state = 2; return WAITING; } goto yy10; } yy10: in->cur = in->mar; goto yy4; yyeof1: #line 68 "c/state/push.re" { return END; } #line 205 "c/state/push.c" #line 70 "c/state/push.re" } void test(const char **packets, Status status) { const char *fname = "pipe"; FILE *fw = fopen(fname, "w"); FILE *fr = fopen(fname, "r"); setvbuf(fw, NULL, _IONBF, 0); setvbuf(fr, NULL, _IONBF, 0); Input in; init(&in, fr); Status st; unsigned int send = 0, recv = 0; for (;;) { st = lex(&in, &recv); if (st == END) { LOG("done: got %u packets\n", recv); break; } else if (st == WAITING) { LOG("waiting...\n"); if (*packets) { LOG("sent packet %u\n", send); fprintf(fw, "%s", *packets++); ++send; } st = fill(&in); LOG("queue: '%s'\n", in.buf); if (st == BIG_PACKET) { LOG("error: packet too big\n"); break; } assert(st == READY); } else { assert(st == BAD_PACKET); LOG("error: ill-formed packet\n"); break; } } LOG("\n"); assert(st == status); if (st == END) assert(recv == send); fclose(fw); fclose(fr); remove(fname); } int main() { const char *packets1[] = {0}; const char *packets2[] = {"zero;", "one;", "two;", "three;", "four;", 0}; const char *packets3[] = {"zer0;", 0}; const char *packets4[] = {"goooooooooogle;", 0}; test(packets1, END); test(packets2, END); test(packets3, BAD_PACKET); test(packets4, BIG_PACKET); return 0; }