xref: /aosp_15_r20/external/libwebsockets/lib/roles/http/minilex.c (revision 1c60b9aca93fdbc9b5f19b2d2194c91294b22281)
1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker  * minilex.c
3*1c60b9acSAndroid Build Coastguard Worker  *
4*1c60b9acSAndroid Build Coastguard Worker  * High efficiency lexical state parser
5*1c60b9acSAndroid Build Coastguard Worker  *
6*1c60b9acSAndroid Build Coastguard Worker  * Copyright (C)2011-2020 Andy Green <[email protected]>
7*1c60b9acSAndroid Build Coastguard Worker  *
8*1c60b9acSAndroid Build Coastguard Worker  * Licensed under MIT
9*1c60b9acSAndroid Build Coastguard Worker  *
10*1c60b9acSAndroid Build Coastguard Worker  * Usage: gcc minilex.c -o minilex && ./minilex > lextable.h
11*1c60b9acSAndroid Build Coastguard Worker  *
12*1c60b9acSAndroid Build Coastguard Worker  * Run it twice to test parsing on the generated table on stderr
13*1c60b9acSAndroid Build Coastguard Worker  *
14*1c60b9acSAndroid Build Coastguard Worker  * Whoo this got a bit complicated by lws-buildtime deselection of some
15*1c60b9acSAndroid Build Coastguard Worker  * headers optionally.  There are 3 x vars, UNCOMMON, WS, H2 so we make
16*1c60b9acSAndroid Build Coastguard Worker  * eight copies of the lextable selected by the appropriate #if defined()
17*1c60b9acSAndroid Build Coastguard Worker  */
18*1c60b9acSAndroid Build Coastguard Worker 
19*1c60b9acSAndroid Build Coastguard Worker #include <stdio.h>
20*1c60b9acSAndroid Build Coastguard Worker #include <stdlib.h>
21*1c60b9acSAndroid Build Coastguard Worker #include <string.h>
22*1c60b9acSAndroid Build Coastguard Worker 
23*1c60b9acSAndroid Build Coastguard Worker /* get all the strings */
24*1c60b9acSAndroid Build Coastguard Worker 
25*1c60b9acSAndroid Build Coastguard Worker #define LWS_ROLE_WS 1
26*1c60b9acSAndroid Build Coastguard Worker #define LWS_WITH_HTTP_UNCOMMON_HEADERS 1
27*1c60b9acSAndroid Build Coastguard Worker #define LWS_ROLE_H2 1
28*1c60b9acSAndroid Build Coastguard Worker 
29*1c60b9acSAndroid Build Coastguard Worker #include "lextable-strings.h"
30*1c60b9acSAndroid Build Coastguard Worker 
31*1c60b9acSAndroid Build Coastguard Worker #undef LWS_ROLE_WS
32*1c60b9acSAndroid Build Coastguard Worker #undef LWS_WITH_HTTP_UNCOMMON_HEADERS
33*1c60b9acSAndroid Build Coastguard Worker #undef LWS_ROLE_H2
34*1c60b9acSAndroid Build Coastguard Worker 
35*1c60b9acSAndroid Build Coastguard Worker /* bitfield for the 8 versions as to which strings exist... index layout
36*1c60b9acSAndroid Build Coastguard Worker  *
37*1c60b9acSAndroid Build Coastguard Worker  *        b0      b1 b2
38*1c60b9acSAndroid Build Coastguard Worker  *  0 =
39*1c60b9acSAndroid Build Coastguard Worker  *  1 = uncommon
40*1c60b9acSAndroid Build Coastguard Worker  *  2 =           ws
41*1c60b9acSAndroid Build Coastguard Worker  *  3 = uncommon  ws
42*1c60b9acSAndroid Build Coastguard Worker  *  4 =              h2
43*1c60b9acSAndroid Build Coastguard Worker  *  5 = uncommon     h2
44*1c60b9acSAndroid Build Coastguard Worker  *  6 =           ws h2
45*1c60b9acSAndroid Build Coastguard Worker  *  7 = uncommon  ws h2
46*1c60b9acSAndroid Build Coastguard Worker  */
47*1c60b9acSAndroid Build Coastguard Worker 
48*1c60b9acSAndroid Build Coastguard Worker unsigned char filter_array[] = {
49*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* get */
50*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* post */
51*1c60b9acSAndroid Build Coastguard Worker 	0xaa, /* options */
52*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* host */
53*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* connection */
54*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* upgrade */
55*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* origin */
56*1c60b9acSAndroid Build Coastguard Worker 	0xcc, /* sec-ws-draft */
57*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* crlf */
58*1c60b9acSAndroid Build Coastguard Worker 	0xcc, /* sec-ws-ext */
59*1c60b9acSAndroid Build Coastguard Worker 	0xcc, /* sec-ws-key1 */
60*1c60b9acSAndroid Build Coastguard Worker 	0xcc, /* sec-ws-key2 */
61*1c60b9acSAndroid Build Coastguard Worker 	0xcc, /* sec-ws-protocol */
62*1c60b9acSAndroid Build Coastguard Worker 	0xcc, /* sec-ws-accept */
63*1c60b9acSAndroid Build Coastguard Worker 	0xcc, /* sec-ws-nonce */
64*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* http/1.1 */
65*1c60b9acSAndroid Build Coastguard Worker 	0xf0, /* http2-settings */
66*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* accept */
67*1c60b9acSAndroid Build Coastguard Worker 	0xaa, /* access-control-req-hdrs */
68*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* if-modified-since */
69*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* if-none-match */
70*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* accept-encoding */
71*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* accept-language */
72*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* pragma */
73*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* cache-control */
74*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* authorization */
75*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* cookie */
76*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* content-length */
77*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* content-type */
78*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* date */
79*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* range */
80*1c60b9acSAndroid Build Coastguard Worker 	0xfa, /* referer */
81*1c60b9acSAndroid Build Coastguard Worker 	0xcc, /* sec-ws-key */
82*1c60b9acSAndroid Build Coastguard Worker 	0xcc, /* sec-ws-version */
83*1c60b9acSAndroid Build Coastguard Worker 	0xcc, /* sec-sc-origin */
84*1c60b9acSAndroid Build Coastguard Worker 	0xf0, /* authority */
85*1c60b9acSAndroid Build Coastguard Worker 	0xf0, /* method */
86*1c60b9acSAndroid Build Coastguard Worker 	0xf0, /* path */
87*1c60b9acSAndroid Build Coastguard Worker 	0xf0, /* scheme */
88*1c60b9acSAndroid Build Coastguard Worker 	0xf0, /* status */
89*1c60b9acSAndroid Build Coastguard Worker 	0xfa, /* accept-charset */
90*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* accept-ranges */
91*1c60b9acSAndroid Build Coastguard Worker 	0xfa, /* access-control-allow-origin */
92*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* age */
93*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* allow */
94*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* content-disposition */
95*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* content-encoding */
96*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* content-language */
97*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* content-location */
98*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* content-range */
99*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* etag */
100*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* expect */
101*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* expires */
102*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* from */
103*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* if-match */
104*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* if-range */
105*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* if-unmodified-since */
106*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* last-modified */
107*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* link */
108*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* location */
109*1c60b9acSAndroid Build Coastguard Worker 	0xfa, /* max-forwards */
110*1c60b9acSAndroid Build Coastguard Worker 	0xfa, /* proxy-authenticate */
111*1c60b9acSAndroid Build Coastguard Worker 	0xfa, /* proxy-authorization */
112*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* refresh */
113*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* retry-after */
114*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* server */
115*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* set-cookie */
116*1c60b9acSAndroid Build Coastguard Worker 	0xfa, /* strict-transport-security */
117*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* transfer-encoding */
118*1c60b9acSAndroid Build Coastguard Worker 	0xfa, /* user-agent */
119*1c60b9acSAndroid Build Coastguard Worker 	0xfa, /* vary */
120*1c60b9acSAndroid Build Coastguard Worker 	0xfa, /* via */
121*1c60b9acSAndroid Build Coastguard Worker 	0xfa, /* www-authenticate */
122*1c60b9acSAndroid Build Coastguard Worker 	0xaa, /* patch */
123*1c60b9acSAndroid Build Coastguard Worker 	0xaa, /* put */
124*1c60b9acSAndroid Build Coastguard Worker 	0xaa, /* delete */
125*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* uri-args */
126*1c60b9acSAndroid Build Coastguard Worker 	0xaa, /* proxy */
127*1c60b9acSAndroid Build Coastguard Worker 	0xaa, /* x-real-ip */
128*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* http/1.0 */
129*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* x-forwarded-for */
130*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* connect */
131*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* head */
132*1c60b9acSAndroid Build Coastguard Worker 	0xfa, /* te */
133*1c60b9acSAndroid Build Coastguard Worker 	0xfa, /* replay-nonce */
134*1c60b9acSAndroid Build Coastguard Worker 	0xf0, /* protocol */
135*1c60b9acSAndroid Build Coastguard Worker 	0xff, /* x-auth-token */
136*1c60b9acSAndroid Build Coastguard Worker 	0xff /* not matchable */
137*1c60b9acSAndroid Build Coastguard Worker };
138*1c60b9acSAndroid Build Coastguard Worker 
139*1c60b9acSAndroid Build Coastguard Worker static unsigned char lws_header_implies_psuedoheader_map[] = {
140*1c60b9acSAndroid Build Coastguard Worker 	0x07, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00 /* <-64 */,
141*1c60b9acSAndroid Build Coastguard Worker 	0x0e /* <- 72 */, 0x24 /* <- 80 */, 0, 0, 0, 0
142*1c60b9acSAndroid Build Coastguard Worker };
143*1c60b9acSAndroid Build Coastguard Worker 
144*1c60b9acSAndroid Build Coastguard Worker /*
145*1c60b9acSAndroid Build Coastguard Worker  * b7 = 0 = 1-byte seq
146*1c60b9acSAndroid Build Coastguard Worker  *	    0x08 = fail
147*1c60b9acSAndroid Build Coastguard Worker  *	    2-byte seq
148*1c60b9acSAndroid Build Coastguard Worker  *	    0x00 - 0x07, then terminal as given in 2nd byte
149*1c60b9acSAndroid Build Coastguard Worker 	    3-byte seq
150*1c60b9acSAndroid Build Coastguard Worker  *	    no match: go fwd 3 byte, match: jump fwd by amt in +1/+2 bytes
151*1c60b9acSAndroid Build Coastguard Worker  *    = 1 = 1-byte seq
152*1c60b9acSAndroid Build Coastguard Worker  *	    no match: die, match go fwd 1 byte
153*1c60b9acSAndroid Build Coastguard Worker  */
154*1c60b9acSAndroid Build Coastguard Worker 
155*1c60b9acSAndroid Build Coastguard Worker unsigned char lextable[][2000] = {
156*1c60b9acSAndroid Build Coastguard Worker 	{
157*1c60b9acSAndroid Build Coastguard Worker 			#include "lextable.h"
158*1c60b9acSAndroid Build Coastguard Worker 	},
159*1c60b9acSAndroid Build Coastguard Worker #define LWS_WITH_HTTP_UNCOMMON_HEADERS
160*1c60b9acSAndroid Build Coastguard Worker 	{
161*1c60b9acSAndroid Build Coastguard Worker 			#include "lextable.h"
162*1c60b9acSAndroid Build Coastguard Worker 	},
163*1c60b9acSAndroid Build Coastguard Worker #undef LWS_WITH_HTTP_UNCOMMON_HEADERS
164*1c60b9acSAndroid Build Coastguard Worker #define LWS_ROLE_WS 1
165*1c60b9acSAndroid Build Coastguard Worker 	{
166*1c60b9acSAndroid Build Coastguard Worker 			#include "lextable.h"
167*1c60b9acSAndroid Build Coastguard Worker 	},
168*1c60b9acSAndroid Build Coastguard Worker #define LWS_WITH_HTTP_UNCOMMON_HEADERS
169*1c60b9acSAndroid Build Coastguard Worker 	{
170*1c60b9acSAndroid Build Coastguard Worker 			#include "lextable.h"
171*1c60b9acSAndroid Build Coastguard Worker 	},
172*1c60b9acSAndroid Build Coastguard Worker #undef LWS_ROLE_WS
173*1c60b9acSAndroid Build Coastguard Worker #undef LWS_WITH_HTTP_UNCOMMON_HEADERS
174*1c60b9acSAndroid Build Coastguard Worker #define LWS_ROLE_H2 1
175*1c60b9acSAndroid Build Coastguard Worker 	{
176*1c60b9acSAndroid Build Coastguard Worker 			#include "lextable.h"
177*1c60b9acSAndroid Build Coastguard Worker 	},
178*1c60b9acSAndroid Build Coastguard Worker #define LWS_WITH_HTTP_UNCOMMON_HEADERS
179*1c60b9acSAndroid Build Coastguard Worker 	{
180*1c60b9acSAndroid Build Coastguard Worker 			#include "lextable.h"
181*1c60b9acSAndroid Build Coastguard Worker 	},
182*1c60b9acSAndroid Build Coastguard Worker #undef LWS_WITH_HTTP_UNCOMMON_HEADERS
183*1c60b9acSAndroid Build Coastguard Worker #define LWS_ROLE_WS 1
184*1c60b9acSAndroid Build Coastguard Worker 	{
185*1c60b9acSAndroid Build Coastguard Worker 			#include "lextable.h"
186*1c60b9acSAndroid Build Coastguard Worker 	},
187*1c60b9acSAndroid Build Coastguard Worker #define LWS_WITH_HTTP_UNCOMMON_HEADERS 1
188*1c60b9acSAndroid Build Coastguard Worker 	{
189*1c60b9acSAndroid Build Coastguard Worker 			#include "lextable.h"
190*1c60b9acSAndroid Build Coastguard Worker 	},
191*1c60b9acSAndroid Build Coastguard Worker };
192*1c60b9acSAndroid Build Coastguard Worker 
193*1c60b9acSAndroid Build Coastguard Worker #define PARALLEL 30
194*1c60b9acSAndroid Build Coastguard Worker 
195*1c60b9acSAndroid Build Coastguard Worker struct state {
196*1c60b9acSAndroid Build Coastguard Worker 	char c[PARALLEL];
197*1c60b9acSAndroid Build Coastguard Worker 	int state[PARALLEL];
198*1c60b9acSAndroid Build Coastguard Worker 	int count;
199*1c60b9acSAndroid Build Coastguard Worker 	int bytepos;
200*1c60b9acSAndroid Build Coastguard Worker 
201*1c60b9acSAndroid Build Coastguard Worker 	int real_pos;
202*1c60b9acSAndroid Build Coastguard Worker };
203*1c60b9acSAndroid Build Coastguard Worker 
204*1c60b9acSAndroid Build Coastguard Worker static unsigned char pseudomap[8][16];
205*1c60b9acSAndroid Build Coastguard Worker 
206*1c60b9acSAndroid Build Coastguard Worker struct state state[1000];
207*1c60b9acSAndroid Build Coastguard Worker int next = 1;
208*1c60b9acSAndroid Build Coastguard Worker 
209*1c60b9acSAndroid Build Coastguard Worker #define FAIL_CHAR 0x08
210*1c60b9acSAndroid Build Coastguard Worker 
lextable_decode(int version,int pos,char c)211*1c60b9acSAndroid Build Coastguard Worker int lextable_decode(int version, int pos, char c)
212*1c60b9acSAndroid Build Coastguard Worker {
213*1c60b9acSAndroid Build Coastguard Worker 	while (1) {
214*1c60b9acSAndroid Build Coastguard Worker 		if (lextable[version][pos] & (1 << 7)) { /* 1-byte, fail on mismatch */
215*1c60b9acSAndroid Build Coastguard Worker 			if ((lextable[version][pos] & 0x7f) != c)
216*1c60b9acSAndroid Build Coastguard Worker 				return -1;
217*1c60b9acSAndroid Build Coastguard Worker 			/* fall thru */
218*1c60b9acSAndroid Build Coastguard Worker 			pos++;
219*1c60b9acSAndroid Build Coastguard Worker 			if (lextable[version][pos] == FAIL_CHAR)
220*1c60b9acSAndroid Build Coastguard Worker 				return -1;
221*1c60b9acSAndroid Build Coastguard Worker 			return pos;
222*1c60b9acSAndroid Build Coastguard Worker 		} else { /* b7 = 0, end or 3-byte */
223*1c60b9acSAndroid Build Coastguard Worker 			if (lextable[version][pos] < FAIL_CHAR) /* terminal marker */
224*1c60b9acSAndroid Build Coastguard Worker 				return pos;
225*1c60b9acSAndroid Build Coastguard Worker 
226*1c60b9acSAndroid Build Coastguard Worker 			if (lextable[version][pos] == c) /* goto */
227*1c60b9acSAndroid Build Coastguard Worker 				return pos + (lextable[version][pos + 1]) +
228*1c60b9acSAndroid Build Coastguard Worker 						(lextable[version][pos + 2] << 8);
229*1c60b9acSAndroid Build Coastguard Worker 			/* fall thru goto */
230*1c60b9acSAndroid Build Coastguard Worker 			pos += 3;
231*1c60b9acSAndroid Build Coastguard Worker 			/* continue */
232*1c60b9acSAndroid Build Coastguard Worker 		}
233*1c60b9acSAndroid Build Coastguard Worker 	}
234*1c60b9acSAndroid Build Coastguard Worker }
235*1c60b9acSAndroid Build Coastguard Worker 
issue(int version)236*1c60b9acSAndroid Build Coastguard Worker int issue(int version)
237*1c60b9acSAndroid Build Coastguard Worker {
238*1c60b9acSAndroid Build Coastguard Worker 	const char *rset[200];
239*1c60b9acSAndroid Build Coastguard Worker 	int n = 0;
240*1c60b9acSAndroid Build Coastguard Worker 	int m;
241*1c60b9acSAndroid Build Coastguard Worker 	int prev;
242*1c60b9acSAndroid Build Coastguard Worker 	int walk;
243*1c60b9acSAndroid Build Coastguard Worker 	int saw;
244*1c60b9acSAndroid Build Coastguard Worker 	int y;
245*1c60b9acSAndroid Build Coastguard Worker 	int j;
246*1c60b9acSAndroid Build Coastguard Worker 	int pos = 0;
247*1c60b9acSAndroid Build Coastguard Worker 
248*1c60b9acSAndroid Build Coastguard Worker 	int setmembers = 0;
249*1c60b9acSAndroid Build Coastguard Worker 
250*1c60b9acSAndroid Build Coastguard Worker 	memset(rset, 0, sizeof(rset));
251*1c60b9acSAndroid Build Coastguard Worker 
252*1c60b9acSAndroid Build Coastguard Worker 	if (version == 7)
253*1c60b9acSAndroid Build Coastguard Worker 		printf("#if defined(LWS_HTTP_HEADERS_ALL) || (%cdefined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && "
254*1c60b9acSAndroid Build Coastguard Worker 			 "%cdefined(LWS_ROLE_WS) && "
255*1c60b9acSAndroid Build Coastguard Worker 			 "%cdefined(LWS_ROLE_H2))\n", version & 1 ? ' ' : '!',
256*1c60b9acSAndroid Build Coastguard Worker 			     version & 2 ? ' ' : '!', version & 4 ? ' ' : '!');
257*1c60b9acSAndroid Build Coastguard Worker 	else
258*1c60b9acSAndroid Build Coastguard Worker 		printf("#if !defined(LWS_HTTP_HEADERS_ALL) && %cdefined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && "
259*1c60b9acSAndroid Build Coastguard Worker 			 "%cdefined(LWS_ROLE_WS) && "
260*1c60b9acSAndroid Build Coastguard Worker 			 "%cdefined(LWS_ROLE_H2)\n", version & 1 ? ' ' : '!',
261*1c60b9acSAndroid Build Coastguard Worker 			     version & 2 ? ' ' : '!', version & 4 ? ' ' : '!');
262*1c60b9acSAndroid Build Coastguard Worker 
263*1c60b9acSAndroid Build Coastguard Worker 	/*
264*1c60b9acSAndroid Build Coastguard Worker 	 * let's create version's view of the set of strings
265*1c60b9acSAndroid Build Coastguard Worker 	 */
266*1c60b9acSAndroid Build Coastguard Worker 
267*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < sizeof(set) / sizeof(set[0]); n++)
268*1c60b9acSAndroid Build Coastguard Worker 		if (filter_array[n] & (1 << version)) {
269*1c60b9acSAndroid Build Coastguard Worker 			printf("\t/* %d: %d: %s */\n", setmembers, n, set[n]);
270*1c60b9acSAndroid Build Coastguard Worker 			if (lws_header_implies_psuedoheader_map[n >> 3] & (1 << (n & 7)))
271*1c60b9acSAndroid Build Coastguard Worker 				pseudomap[version][(setmembers >> 3)] |= 1 << (setmembers & 7);
272*1c60b9acSAndroid Build Coastguard Worker 			rset[setmembers++] = set[n];
273*1c60b9acSAndroid Build Coastguard Worker 		}
274*1c60b9acSAndroid Build Coastguard Worker 
275*1c60b9acSAndroid Build Coastguard Worker 	n = 0;
276*1c60b9acSAndroid Build Coastguard Worker 	while (n < setmembers) {
277*1c60b9acSAndroid Build Coastguard Worker 
278*1c60b9acSAndroid Build Coastguard Worker 		m = 0;
279*1c60b9acSAndroid Build Coastguard Worker 		walk = 0;
280*1c60b9acSAndroid Build Coastguard Worker 		prev = 0;
281*1c60b9acSAndroid Build Coastguard Worker 
282*1c60b9acSAndroid Build Coastguard Worker 		if (rset[n][0] == '\0') {
283*1c60b9acSAndroid Build Coastguard Worker 			n++;
284*1c60b9acSAndroid Build Coastguard Worker 			continue;
285*1c60b9acSAndroid Build Coastguard Worker 		}
286*1c60b9acSAndroid Build Coastguard Worker 
287*1c60b9acSAndroid Build Coastguard Worker 		while (rset[n][m]) {
288*1c60b9acSAndroid Build Coastguard Worker 
289*1c60b9acSAndroid Build Coastguard Worker 			saw = 0;
290*1c60b9acSAndroid Build Coastguard Worker 			for (y = 0; y < state[walk].count; y++)
291*1c60b9acSAndroid Build Coastguard Worker 				if (state[walk].c[y] == rset[n][m]) {
292*1c60b9acSAndroid Build Coastguard Worker 					/* exists -- go forward */
293*1c60b9acSAndroid Build Coastguard Worker 					walk = state[walk].state[y];
294*1c60b9acSAndroid Build Coastguard Worker 					saw = 1;
295*1c60b9acSAndroid Build Coastguard Worker 					break;
296*1c60b9acSAndroid Build Coastguard Worker 				}
297*1c60b9acSAndroid Build Coastguard Worker 
298*1c60b9acSAndroid Build Coastguard Worker 			if (saw)
299*1c60b9acSAndroid Build Coastguard Worker 				goto again;
300*1c60b9acSAndroid Build Coastguard Worker 
301*1c60b9acSAndroid Build Coastguard Worker 			/* something we didn't see before */
302*1c60b9acSAndroid Build Coastguard Worker 
303*1c60b9acSAndroid Build Coastguard Worker 			state[walk].c[state[walk].count] = rset[n][m];
304*1c60b9acSAndroid Build Coastguard Worker 
305*1c60b9acSAndroid Build Coastguard Worker 			state[walk].state[state[walk].count] = next;
306*1c60b9acSAndroid Build Coastguard Worker 			state[walk].count++;
307*1c60b9acSAndroid Build Coastguard Worker 			walk = next++;
308*1c60b9acSAndroid Build Coastguard Worker again:
309*1c60b9acSAndroid Build Coastguard Worker 			m++;
310*1c60b9acSAndroid Build Coastguard Worker 		}
311*1c60b9acSAndroid Build Coastguard Worker 
312*1c60b9acSAndroid Build Coastguard Worker 		state[walk].c[0] = n++;
313*1c60b9acSAndroid Build Coastguard Worker 		state[walk].state[0] = 0; /* terminal marker */
314*1c60b9acSAndroid Build Coastguard Worker 		state[walk].count = 1;
315*1c60b9acSAndroid Build Coastguard Worker 	}
316*1c60b9acSAndroid Build Coastguard Worker 
317*1c60b9acSAndroid Build Coastguard Worker 	walk = 0;
318*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < next; n++) {
319*1c60b9acSAndroid Build Coastguard Worker 		state[n].bytepos = walk;
320*1c60b9acSAndroid Build Coastguard Worker 		walk += (2 * state[n].count);
321*1c60b9acSAndroid Build Coastguard Worker 	}
322*1c60b9acSAndroid Build Coastguard Worker 
323*1c60b9acSAndroid Build Coastguard Worker 	/* compute everyone's position first */
324*1c60b9acSAndroid Build Coastguard Worker 
325*1c60b9acSAndroid Build Coastguard Worker 	pos = 0;
326*1c60b9acSAndroid Build Coastguard Worker 	walk = 0;
327*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < next; n++) {
328*1c60b9acSAndroid Build Coastguard Worker 
329*1c60b9acSAndroid Build Coastguard Worker 		state[n].real_pos = pos;
330*1c60b9acSAndroid Build Coastguard Worker 
331*1c60b9acSAndroid Build Coastguard Worker 		for (m = 0; m < state[n].count; m++) {
332*1c60b9acSAndroid Build Coastguard Worker 
333*1c60b9acSAndroid Build Coastguard Worker 			if (state[n].state[m] == 0)
334*1c60b9acSAndroid Build Coastguard Worker 				pos += 2; /* terminal marker */
335*1c60b9acSAndroid Build Coastguard Worker 			else { /* c is a character */
336*1c60b9acSAndroid Build Coastguard Worker 				if ((state[state[n].state[m]].bytepos -
337*1c60b9acSAndroid Build Coastguard Worker 								walk) == 2)
338*1c60b9acSAndroid Build Coastguard Worker 					pos++;
339*1c60b9acSAndroid Build Coastguard Worker 				else {
340*1c60b9acSAndroid Build Coastguard Worker 					pos += 3;
341*1c60b9acSAndroid Build Coastguard Worker 					if (m == state[n].count - 1)
342*1c60b9acSAndroid Build Coastguard Worker 						pos++; /* fail */
343*1c60b9acSAndroid Build Coastguard Worker 				}
344*1c60b9acSAndroid Build Coastguard Worker 			}
345*1c60b9acSAndroid Build Coastguard Worker 			walk += 2;
346*1c60b9acSAndroid Build Coastguard Worker 		}
347*1c60b9acSAndroid Build Coastguard Worker 	}
348*1c60b9acSAndroid Build Coastguard Worker 
349*1c60b9acSAndroid Build Coastguard Worker 	walk = 0;
350*1c60b9acSAndroid Build Coastguard Worker 	pos = 0;
351*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < next; n++) {
352*1c60b9acSAndroid Build Coastguard Worker 		for (m = 0; m < state[n].count; m++) {
353*1c60b9acSAndroid Build Coastguard Worker 
354*1c60b9acSAndroid Build Coastguard Worker 			if (!m)
355*1c60b9acSAndroid Build Coastguard Worker 				fprintf(stdout, "/* pos %04x: %3d */ ",
356*1c60b9acSAndroid Build Coastguard Worker 							  state[n].real_pos, n);
357*1c60b9acSAndroid Build Coastguard Worker 			else
358*1c60b9acSAndroid Build Coastguard Worker 				fprintf(stdout, "                    ");
359*1c60b9acSAndroid Build Coastguard Worker 
360*1c60b9acSAndroid Build Coastguard Worker 			y = state[n].c[m];
361*1c60b9acSAndroid Build Coastguard Worker 			saw = state[n].state[m];
362*1c60b9acSAndroid Build Coastguard Worker 
363*1c60b9acSAndroid Build Coastguard Worker 			if (saw == 0) { // c is a terminal then
364*1c60b9acSAndroid Build Coastguard Worker 
365*1c60b9acSAndroid Build Coastguard Worker 				if (y > 0x7ff) {
366*1c60b9acSAndroid Build Coastguard Worker 					fprintf(stderr, "terminal too big\n");
367*1c60b9acSAndroid Build Coastguard Worker 					return 2;
368*1c60b9acSAndroid Build Coastguard Worker 				}
369*1c60b9acSAndroid Build Coastguard Worker 
370*1c60b9acSAndroid Build Coastguard Worker 				fprintf(stdout, "   0x%02X, 0x%02X           "
371*1c60b9acSAndroid Build Coastguard Worker 					"       "
372*1c60b9acSAndroid Build Coastguard Worker 					"/* - terminal marker %2d - */,\n",
373*1c60b9acSAndroid Build Coastguard Worker 						    y >> 8, y & 0xff, y & 0x7f);
374*1c60b9acSAndroid Build Coastguard Worker 				pos += 2;
375*1c60b9acSAndroid Build Coastguard Worker 				walk += 2;
376*1c60b9acSAndroid Build Coastguard Worker 				continue;
377*1c60b9acSAndroid Build Coastguard Worker 			}
378*1c60b9acSAndroid Build Coastguard Worker 
379*1c60b9acSAndroid Build Coastguard Worker 			/* c is a character */
380*1c60b9acSAndroid Build Coastguard Worker 
381*1c60b9acSAndroid Build Coastguard Worker 			prev = y &0x7f;
382*1c60b9acSAndroid Build Coastguard Worker 			if (prev < 32 || prev > 126)
383*1c60b9acSAndroid Build Coastguard Worker 				prev = '.';
384*1c60b9acSAndroid Build Coastguard Worker 
385*1c60b9acSAndroid Build Coastguard Worker 
386*1c60b9acSAndroid Build Coastguard Worker 			if ((state[saw].bytepos - walk) == 2) {
387*1c60b9acSAndroid Build Coastguard Worker 				fprintf(stdout, "   0x%02X /* '%c' -> */,\n",
388*1c60b9acSAndroid Build Coastguard Worker 						y | 0x80, prev);
389*1c60b9acSAndroid Build Coastguard Worker 				pos++;
390*1c60b9acSAndroid Build Coastguard Worker 				walk += 2;
391*1c60b9acSAndroid Build Coastguard Worker 				continue;
392*1c60b9acSAndroid Build Coastguard Worker 			}
393*1c60b9acSAndroid Build Coastguard Worker 
394*1c60b9acSAndroid Build Coastguard Worker 			j = state[saw].real_pos - pos;
395*1c60b9acSAndroid Build Coastguard Worker 
396*1c60b9acSAndroid Build Coastguard Worker 			if (j > 0xffff) {
397*1c60b9acSAndroid Build Coastguard Worker 				fprintf(stderr,
398*1c60b9acSAndroid Build Coastguard Worker 				  "Jump > 64K bytes ahead (%d to %d)\n",
399*1c60b9acSAndroid Build Coastguard Worker 					state[n].real_pos, state[saw].real_pos);
400*1c60b9acSAndroid Build Coastguard Worker 				return 1;
401*1c60b9acSAndroid Build Coastguard Worker 			}
402*1c60b9acSAndroid Build Coastguard Worker 			fprintf(stdout, "   0x%02X /* '%c' */, 0x%02X, 0x%02X  "
403*1c60b9acSAndroid Build Coastguard Worker 				"/* (to 0x%04X state %3d) */,\n",
404*1c60b9acSAndroid Build Coastguard Worker 				y, prev,
405*1c60b9acSAndroid Build Coastguard Worker 				j & 0xff, j >> 8,
406*1c60b9acSAndroid Build Coastguard Worker 				state[saw].real_pos, saw);
407*1c60b9acSAndroid Build Coastguard Worker 			pos += 3;
408*1c60b9acSAndroid Build Coastguard Worker 
409*1c60b9acSAndroid Build Coastguard Worker 			if (m == state[n].count - 1) {
410*1c60b9acSAndroid Build Coastguard Worker 				fprintf(stdout,
411*1c60b9acSAndroid Build Coastguard Worker 				  "                       0x%02X, /* fail */\n",
412*1c60b9acSAndroid Build Coastguard Worker 								FAIL_CHAR);
413*1c60b9acSAndroid Build Coastguard Worker 				pos++; /* fail */
414*1c60b9acSAndroid Build Coastguard Worker 			}
415*1c60b9acSAndroid Build Coastguard Worker 
416*1c60b9acSAndroid Build Coastguard Worker 			walk += 2;
417*1c60b9acSAndroid Build Coastguard Worker 		}
418*1c60b9acSAndroid Build Coastguard Worker 	}
419*1c60b9acSAndroid Build Coastguard Worker 
420*1c60b9acSAndroid Build Coastguard Worker 	fprintf(stdout, "/* total size %d bytes */\n", pos);
421*1c60b9acSAndroid Build Coastguard Worker 
422*1c60b9acSAndroid Build Coastguard Worker 	printf("#endif\n\n");
423*1c60b9acSAndroid Build Coastguard Worker 
424*1c60b9acSAndroid Build Coastguard Worker 	/*
425*1c60b9acSAndroid Build Coastguard Worker 	 * Try to parse every legal input string
426*1c60b9acSAndroid Build Coastguard Worker 	 */
427*1c60b9acSAndroid Build Coastguard Worker 
428*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < setmembers; n++) {
429*1c60b9acSAndroid Build Coastguard Worker 		walk = 0;
430*1c60b9acSAndroid Build Coastguard Worker 		m = 0;
431*1c60b9acSAndroid Build Coastguard Worker 		y = -1;
432*1c60b9acSAndroid Build Coastguard Worker 
433*1c60b9acSAndroid Build Coastguard Worker 		if (rset[n][0] == '\0')
434*1c60b9acSAndroid Build Coastguard Worker 			continue;
435*1c60b9acSAndroid Build Coastguard Worker 
436*1c60b9acSAndroid Build Coastguard Worker 		fprintf(stderr, "  trying %d '%s'\n", n, rset[n]);
437*1c60b9acSAndroid Build Coastguard Worker 
438*1c60b9acSAndroid Build Coastguard Worker 		while (rset[n][m]) {
439*1c60b9acSAndroid Build Coastguard Worker 			walk = lextable_decode(version, walk, rset[n][m]);
440*1c60b9acSAndroid Build Coastguard Worker 			if (walk < 0) {
441*1c60b9acSAndroid Build Coastguard Worker 				fprintf(stderr, "failed\n");
442*1c60b9acSAndroid Build Coastguard Worker 				return 3;
443*1c60b9acSAndroid Build Coastguard Worker 			}
444*1c60b9acSAndroid Build Coastguard Worker 
445*1c60b9acSAndroid Build Coastguard Worker 			if (lextable[version][walk] < FAIL_CHAR) {
446*1c60b9acSAndroid Build Coastguard Worker 				y = (lextable[version][walk] << 8) +
447*1c60b9acSAndroid Build Coastguard Worker 				     lextable[version][walk + 1];
448*1c60b9acSAndroid Build Coastguard Worker 				break;
449*1c60b9acSAndroid Build Coastguard Worker 			}
450*1c60b9acSAndroid Build Coastguard Worker 			m++;
451*1c60b9acSAndroid Build Coastguard Worker 		}
452*1c60b9acSAndroid Build Coastguard Worker 
453*1c60b9acSAndroid Build Coastguard Worker 		if (y != n) {
454*1c60b9acSAndroid Build Coastguard Worker 			fprintf(stderr, "decode failed %d\n", y);
455*1c60b9acSAndroid Build Coastguard Worker 			return 4;
456*1c60b9acSAndroid Build Coastguard Worker 		}
457*1c60b9acSAndroid Build Coastguard Worker 	}
458*1c60b9acSAndroid Build Coastguard Worker 
459*1c60b9acSAndroid Build Coastguard Worker 	fprintf(stderr, "All decode OK\n");
460*1c60b9acSAndroid Build Coastguard Worker 
461*1c60b9acSAndroid Build Coastguard Worker 	return 0;
462*1c60b9acSAndroid Build Coastguard Worker }
463*1c60b9acSAndroid Build Coastguard Worker 
main(void)464*1c60b9acSAndroid Build Coastguard Worker int main(void)
465*1c60b9acSAndroid Build Coastguard Worker {
466*1c60b9acSAndroid Build Coastguard Worker 	int m, n;
467*1c60b9acSAndroid Build Coastguard Worker 
468*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < 8; n++) {
469*1c60b9acSAndroid Build Coastguard Worker 		issue(n);
470*1c60b9acSAndroid Build Coastguard Worker 	}
471*1c60b9acSAndroid Build Coastguard Worker 
472*1c60b9acSAndroid Build Coastguard Worker 	printf("\n/*\n");
473*1c60b9acSAndroid Build Coastguard Worker 
474*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < 8; n++) {
475*1c60b9acSAndroid Build Coastguard Worker 
476*1c60b9acSAndroid Build Coastguard Worker 		if (n == 7)
477*1c60b9acSAndroid Build Coastguard Worker 			printf("#if defined(LWS_HTTP_HEADERS_ALL) || (%cdefined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && "
478*1c60b9acSAndroid Build Coastguard Worker 				 "%cdefined(LWS_ROLE_WS) && "
479*1c60b9acSAndroid Build Coastguard Worker 				 "%cdefined(LWS_ROLE_H2))\n", n & 1 ? ' ' : '!',
480*1c60b9acSAndroid Build Coastguard Worker 				     n & 2 ? ' ' : '!', n & 4 ? ' ' : '!');
481*1c60b9acSAndroid Build Coastguard Worker 		else
482*1c60b9acSAndroid Build Coastguard Worker 		printf("#if !defined(LWS_HTTP_HEADERS_ALL) && %cdefined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && "
483*1c60b9acSAndroid Build Coastguard Worker 			 "%cdefined(LWS_ROLE_WS) && "
484*1c60b9acSAndroid Build Coastguard Worker 			 "%cdefined(LWS_ROLE_H2)\n", n & 1 ? ' ' : '!',
485*1c60b9acSAndroid Build Coastguard Worker 			     n & 2 ? ' ' : '!', n & 4 ? ' ' : '!');
486*1c60b9acSAndroid Build Coastguard Worker 
487*1c60b9acSAndroid Build Coastguard Worker 		printf("static uint8_t lws_header_implies_psuedoheader_map[] = {\n\t");
488*1c60b9acSAndroid Build Coastguard Worker 
489*1c60b9acSAndroid Build Coastguard Worker 		for (m = 0; m < sizeof(pseudomap[n]); m++)
490*1c60b9acSAndroid Build Coastguard Worker 			printf("0x%02x,", pseudomap[n][m]);
491*1c60b9acSAndroid Build Coastguard Worker 
492*1c60b9acSAndroid Build Coastguard Worker 		printf("\n};\n");
493*1c60b9acSAndroid Build Coastguard Worker 
494*1c60b9acSAndroid Build Coastguard Worker 		printf("#endif\n");
495*1c60b9acSAndroid Build Coastguard Worker 	}
496*1c60b9acSAndroid Build Coastguard Worker 
497*1c60b9acSAndroid Build Coastguard Worker 	printf("*/\n");
498*1c60b9acSAndroid Build Coastguard Worker 
499*1c60b9acSAndroid Build Coastguard Worker 	fprintf(stderr, "did all the variants\n");
500*1c60b9acSAndroid Build Coastguard Worker }
501