improve minilex use external parsing header
Clean up minilex
Move the header output to stdout
Introduce lexfile.h as the header output
Use lexfile.h in both minilex itself and lws
Add the following header support
"Accept:",
"If-Modified-Since:",
"Accept-Encoding:",
"Accept-Language:",
"Pragma:",
"Cache-Control:",
"Authorization:",
"Cookie:",
"Content-Type:",
"Date:",
"Range:",
"Referer:"
Signed-off-by: Andy Green <andy.green@linaro.org>
2013-11-09 10:09:09 +08:00
|
|
|
/*
|
|
|
|
* minilex.c
|
|
|
|
*
|
|
|
|
* High efficiency lexical state parser
|
|
|
|
*
|
|
|
|
* Copyright (C)2011-2013 Andy Green <andy@warmcat.com>
|
|
|
|
*
|
|
|
|
* Licensed under LGPL2
|
|
|
|
*
|
|
|
|
* Usage: gcc minilex.c -o minilex && ./minilex > lextable.h
|
|
|
|
*
|
|
|
|
* Run it twice to test parsing on the generated table on stderr
|
|
|
|
*/
|
|
|
|
|
2013-01-18 01:55:48 +08:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2013-11-13 08:03:05 +08:00
|
|
|
/* set of parsable strings -- ALL LOWER CASE */
|
improve minilex use external parsing header
Clean up minilex
Move the header output to stdout
Introduce lexfile.h as the header output
Use lexfile.h in both minilex itself and lws
Add the following header support
"Accept:",
"If-Modified-Since:",
"Accept-Encoding:",
"Accept-Language:",
"Pragma:",
"Cache-Control:",
"Authorization:",
"Cookie:",
"Content-Type:",
"Date:",
"Range:",
"Referer:"
Signed-off-by: Andy Green <andy.green@linaro.org>
2013-11-09 10:09:09 +08:00
|
|
|
|
2013-01-18 01:55:48 +08:00
|
|
|
const char *set[] = {
|
2013-11-13 08:03:05 +08:00
|
|
|
"get ",
|
|
|
|
"host:",
|
|
|
|
"connection:",
|
|
|
|
"sec-websocket-key1:",
|
|
|
|
"sec-websocket-key2:",
|
|
|
|
"sec-websocket-protocol:",
|
|
|
|
"upgrade:",
|
|
|
|
"origin:",
|
|
|
|
"sec-websocket-draft:",
|
2013-01-18 01:55:48 +08:00
|
|
|
"\x0d\x0a",
|
|
|
|
|
2013-11-13 08:03:05 +08:00
|
|
|
"sec-websocket-key:",
|
|
|
|
"sec-websocket-version:",
|
|
|
|
"sec-websocket-origin:",
|
|
|
|
|
|
|
|
"sec-websocket-extensions:",
|
|
|
|
|
|
|
|
"sec-websocket-accept:",
|
|
|
|
"sec-websocket-nonce:",
|
|
|
|
"http/1.1 ",
|
|
|
|
|
|
|
|
"accept:",
|
|
|
|
"if-modified-since:",
|
|
|
|
"accept-encoding:",
|
|
|
|
"accept-language:",
|
|
|
|
"pragma:",
|
|
|
|
"cache-control:",
|
|
|
|
"authorization:",
|
|
|
|
"cookie:",
|
|
|
|
"content-type:",
|
|
|
|
"date:",
|
|
|
|
"range:",
|
|
|
|
"referer:",
|
|
|
|
"", /* not matchable */
|
|
|
|
|
2013-01-18 01:55:48 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
unsigned char lextable[] = {
|
improve minilex use external parsing header
Clean up minilex
Move the header output to stdout
Introduce lexfile.h as the header output
Use lexfile.h in both minilex itself and lws
Add the following header support
"Accept:",
"If-Modified-Since:",
"Accept-Encoding:",
"Accept-Language:",
"Pragma:",
"Cache-Control:",
"Authorization:",
"Cookie:",
"Content-Type:",
"Date:",
"Range:",
"Referer:"
Signed-off-by: Andy Green <andy.green@linaro.org>
2013-11-09 10:09:09 +08:00
|
|
|
#include "lextable.h"
|
2013-01-18 01:55:48 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
#define PARALLEL 30
|
|
|
|
|
|
|
|
struct state {
|
|
|
|
char c[PARALLEL];
|
|
|
|
int state[PARALLEL];
|
|
|
|
int count;
|
|
|
|
int bytepos;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct state state[1000];
|
|
|
|
int next = 1;
|
|
|
|
|
improve minilex use external parsing header
Clean up minilex
Move the header output to stdout
Introduce lexfile.h as the header output
Use lexfile.h in both minilex itself and lws
Add the following header support
"Accept:",
"If-Modified-Since:",
"Accept-Encoding:",
"Accept-Language:",
"Pragma:",
"Cache-Control:",
"Authorization:",
"Cookie:",
"Content-Type:",
"Date:",
"Range:",
"Referer:"
Signed-off-by: Andy Green <andy.green@linaro.org>
2013-11-09 10:09:09 +08:00
|
|
|
|
2013-01-18 01:55:48 +08:00
|
|
|
int lextable_decode(int pos, char c)
|
|
|
|
{
|
|
|
|
while (1) {
|
improve minilex use external parsing header
Clean up minilex
Move the header output to stdout
Introduce lexfile.h as the header output
Use lexfile.h in both minilex itself and lws
Add the following header support
"Accept:",
"If-Modified-Since:",
"Accept-Encoding:",
"Accept-Language:",
"Pragma:",
"Cache-Control:",
"Authorization:",
"Cookie:",
"Content-Type:",
"Date:",
"Range:",
"Referer:"
Signed-off-by: Andy Green <andy.green@linaro.org>
2013-11-09 10:09:09 +08:00
|
|
|
if (!lextable[pos + 1]) /* terminal marker */
|
2013-01-18 01:55:48 +08:00
|
|
|
return pos;
|
|
|
|
|
improve minilex use external parsing header
Clean up minilex
Move the header output to stdout
Introduce lexfile.h as the header output
Use lexfile.h in both minilex itself and lws
Add the following header support
"Accept:",
"If-Modified-Since:",
"Accept-Encoding:",
"Accept-Language:",
"Pragma:",
"Cache-Control:",
"Authorization:",
"Cookie:",
"Content-Type:",
"Date:",
"Range:",
"Referer:"
Signed-off-by: Andy Green <andy.green@linaro.org>
2013-11-09 10:09:09 +08:00
|
|
|
if ((lextable[pos] & 0x7f) == c) /* goto */
|
2013-01-18 01:55:48 +08:00
|
|
|
return pos + (lextable[pos + 1] << 1);
|
|
|
|
|
improve minilex use external parsing header
Clean up minilex
Move the header output to stdout
Introduce lexfile.h as the header output
Use lexfile.h in both minilex itself and lws
Add the following header support
"Accept:",
"If-Modified-Since:",
"Accept-Encoding:",
"Accept-Language:",
"Pragma:",
"Cache-Control:",
"Authorization:",
"Cookie:",
"Content-Type:",
"Date:",
"Range:",
"Referer:"
Signed-off-by: Andy Green <andy.green@linaro.org>
2013-11-09 10:09:09 +08:00
|
|
|
if (lextable[pos] & 0x80) /* fail */
|
2013-01-18 01:55:48 +08:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
pos += 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int main(void)
|
|
|
|
{
|
|
|
|
int n = 0;
|
|
|
|
int m = 0;
|
|
|
|
int prev;
|
|
|
|
char c;
|
|
|
|
int walk;
|
|
|
|
int saw;
|
|
|
|
int y;
|
|
|
|
|
|
|
|
while (n < sizeof(set) / sizeof(set[0])) {
|
|
|
|
|
|
|
|
m = 0;
|
|
|
|
walk = 0;
|
|
|
|
prev = 0;
|
|
|
|
|
2013-11-13 08:03:05 +08:00
|
|
|
if (set[n][0] == '\0') {
|
|
|
|
n++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2013-01-18 01:55:48 +08:00
|
|
|
while (set[n][m]) {
|
|
|
|
|
|
|
|
saw = 0;
|
|
|
|
for (y = 0; y < state[walk].count; y++)
|
improve minilex use external parsing header
Clean up minilex
Move the header output to stdout
Introduce lexfile.h as the header output
Use lexfile.h in both minilex itself and lws
Add the following header support
"Accept:",
"If-Modified-Since:",
"Accept-Encoding:",
"Accept-Language:",
"Pragma:",
"Cache-Control:",
"Authorization:",
"Cookie:",
"Content-Type:",
"Date:",
"Range:",
"Referer:"
Signed-off-by: Andy Green <andy.green@linaro.org>
2013-11-09 10:09:09 +08:00
|
|
|
if (state[walk].c[y] == set[n][m]) {
|
|
|
|
/* exists -- go forward */
|
|
|
|
walk = state[walk].state[y];
|
2013-01-18 01:55:48 +08:00
|
|
|
saw = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (saw)
|
|
|
|
goto again;
|
|
|
|
|
|
|
|
/* something we didn't see before */
|
|
|
|
|
|
|
|
state[walk].c[state[walk].count] = set[n][m];
|
|
|
|
|
|
|
|
state[walk].state[state[walk].count] = next;
|
|
|
|
state[walk].count++;
|
improve minilex use external parsing header
Clean up minilex
Move the header output to stdout
Introduce lexfile.h as the header output
Use lexfile.h in both minilex itself and lws
Add the following header support
"Accept:",
"If-Modified-Since:",
"Accept-Encoding:",
"Accept-Language:",
"Pragma:",
"Cache-Control:",
"Authorization:",
"Cookie:",
"Content-Type:",
"Date:",
"Range:",
"Referer:"
Signed-off-by: Andy Green <andy.green@linaro.org>
2013-11-09 10:09:09 +08:00
|
|
|
walk = next++;
|
2013-01-18 01:55:48 +08:00
|
|
|
again:
|
|
|
|
m++;
|
|
|
|
}
|
|
|
|
|
improve minilex use external parsing header
Clean up minilex
Move the header output to stdout
Introduce lexfile.h as the header output
Use lexfile.h in both minilex itself and lws
Add the following header support
"Accept:",
"If-Modified-Since:",
"Accept-Encoding:",
"Accept-Language:",
"Pragma:",
"Cache-Control:",
"Authorization:",
"Cookie:",
"Content-Type:",
"Date:",
"Range:",
"Referer:"
Signed-off-by: Andy Green <andy.green@linaro.org>
2013-11-09 10:09:09 +08:00
|
|
|
state[walk].c[0] = n++;
|
2013-01-18 01:55:48 +08:00
|
|
|
state[walk].state[0] = 0; /* terminal marker */
|
|
|
|
state[walk].count = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
walk = 0;
|
|
|
|
for (n = 0; n < next; n++) {
|
|
|
|
state[n].bytepos = walk;
|
|
|
|
walk += (2 * state[n].count);
|
|
|
|
}
|
|
|
|
|
|
|
|
walk = 0;
|
|
|
|
for (n = 0; n < next; n++) {
|
|
|
|
for (m = 0; m < state[n].count; m++) {
|
improve minilex use external parsing header
Clean up minilex
Move the header output to stdout
Introduce lexfile.h as the header output
Use lexfile.h in both minilex itself and lws
Add the following header support
"Accept:",
"If-Modified-Since:",
"Accept-Encoding:",
"Accept-Language:",
"Pragma:",
"Cache-Control:",
"Authorization:",
"Cookie:",
"Content-Type:",
"Date:",
"Range:",
"Referer:"
Signed-off-by: Andy Green <andy.green@linaro.org>
2013-11-09 10:09:09 +08:00
|
|
|
|
|
|
|
if (!m)
|
|
|
|
fprintf(stdout, "/* pos %3d: state %3d */ ",
|
|
|
|
walk, n);
|
|
|
|
else
|
|
|
|
fprintf(stdout, " ");
|
|
|
|
|
2013-01-18 01:55:48 +08:00
|
|
|
y = state[n].c[m];
|
|
|
|
saw = state[n].state[m];
|
|
|
|
|
|
|
|
if (m == state[n].count - 1)
|
|
|
|
y |= 0x80; /* last option */
|
|
|
|
|
|
|
|
if (saw == 0) // c is a terminal then
|
improve minilex use external parsing header
Clean up minilex
Move the header output to stdout
Introduce lexfile.h as the header output
Use lexfile.h in both minilex itself and lws
Add the following header support
"Accept:",
"If-Modified-Since:",
"Accept-Encoding:",
"Accept-Language:",
"Pragma:",
"Cache-Control:",
"Authorization:",
"Cookie:",
"Content-Type:",
"Date:",
"Range:",
"Referer:"
Signed-off-by: Andy Green <andy.green@linaro.org>
2013-11-09 10:09:09 +08:00
|
|
|
fprintf(stdout, " 0x%02X, 0x00 "
|
|
|
|
"/* - terminal marker %2d - */, \n",
|
|
|
|
y, y - 0x80);
|
|
|
|
else { /* c is a character and we need a byte delta */
|
2013-01-18 01:55:48 +08:00
|
|
|
if ((state[saw].bytepos - walk) / 2 > 0xff) {
|
improve minilex use external parsing header
Clean up minilex
Move the header output to stdout
Introduce lexfile.h as the header output
Use lexfile.h in both minilex itself and lws
Add the following header support
"Accept:",
"If-Modified-Since:",
"Accept-Encoding:",
"Accept-Language:",
"Pragma:",
"Cache-Control:",
"Authorization:",
"Cookie:",
"Content-Type:",
"Date:",
"Range:",
"Referer:"
Signed-off-by: Andy Green <andy.green@linaro.org>
2013-11-09 10:09:09 +08:00
|
|
|
fprintf(stdout,
|
|
|
|
"Tried to jump > 510 bytes ahead\n");
|
2013-01-18 01:55:48 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
prev = y &0x7f;
|
|
|
|
if (prev < 32 || prev > 126)
|
|
|
|
prev = '.';
|
improve minilex use external parsing header
Clean up minilex
Move the header output to stdout
Introduce lexfile.h as the header output
Use lexfile.h in both minilex itself and lws
Add the following header support
"Accept:",
"If-Modified-Since:",
"Accept-Encoding:",
"Accept-Language:",
"Pragma:",
"Cache-Control:",
"Authorization:",
"Cookie:",
"Content-Type:",
"Date:",
"Range:",
"Referer:"
Signed-off-by: Andy Green <andy.green@linaro.org>
2013-11-09 10:09:09 +08:00
|
|
|
fprintf(stdout, " 0x%02X /* '%c' */, 0x%02X "
|
|
|
|
"/* (to pos %3d state %3d) */,\n",
|
|
|
|
y, prev,
|
|
|
|
(state[saw].bytepos - walk) / 2,
|
|
|
|
state[saw].bytepos, saw);
|
2013-01-18 01:55:48 +08:00
|
|
|
}
|
|
|
|
walk += 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
improve minilex use external parsing header
Clean up minilex
Move the header output to stdout
Introduce lexfile.h as the header output
Use lexfile.h in both minilex itself and lws
Add the following header support
"Accept:",
"If-Modified-Since:",
"Accept-Encoding:",
"Accept-Language:",
"Pragma:",
"Cache-Control:",
"Authorization:",
"Cookie:",
"Content-Type:",
"Date:",
"Range:",
"Referer:"
Signed-off-by: Andy Green <andy.green@linaro.org>
2013-11-09 10:09:09 +08:00
|
|
|
fprintf(stdout, "/* total size %d bytes */\n", walk);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Test parser... real parser code is the same
|
|
|
|
*/
|
2013-01-18 01:55:48 +08:00
|
|
|
|
|
|
|
for (n = 0; n < sizeof(set) / sizeof(set[0]); n++) {
|
|
|
|
walk = 0;
|
|
|
|
m = 0;
|
|
|
|
|
2013-11-13 08:03:05 +08:00
|
|
|
if (set[n][0] == '\0')
|
|
|
|
continue;
|
|
|
|
|
improve minilex use external parsing header
Clean up minilex
Move the header output to stdout
Introduce lexfile.h as the header output
Use lexfile.h in both minilex itself and lws
Add the following header support
"Accept:",
"If-Modified-Since:",
"Accept-Encoding:",
"Accept-Language:",
"Pragma:",
"Cache-Control:",
"Authorization:",
"Cookie:",
"Content-Type:",
"Date:",
"Range:",
"Referer:"
Signed-off-by: Andy Green <andy.green@linaro.org>
2013-11-09 10:09:09 +08:00
|
|
|
fprintf(stderr, "Trying '%s'\n", set[n]);
|
2013-01-18 01:55:48 +08:00
|
|
|
|
|
|
|
while (set[n][m]) {
|
|
|
|
walk = lextable_decode(walk, set[n][m]);
|
|
|
|
if (walk < 0) {
|
|
|
|
fprintf(stderr, "failed\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (lextable[walk + 1] == 0) {
|
improve minilex use external parsing header
Clean up minilex
Move the header output to stdout
Introduce lexfile.h as the header output
Use lexfile.h in both minilex itself and lws
Add the following header support
"Accept:",
"If-Modified-Since:",
"Accept-Encoding:",
"Accept-Language:",
"Pragma:",
"Cache-Control:",
"Authorization:",
"Cookie:",
"Content-Type:",
"Date:",
"Range:",
"Referer:"
Signed-off-by: Andy Green <andy.green@linaro.org>
2013-11-09 10:09:09 +08:00
|
|
|
fprintf(stderr, "decode: %d\n",
|
|
|
|
lextable[walk] & 0x7f);
|
2013-01-18 01:55:48 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
m++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|