waitress-core 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +4 -4
  3. data/LICENSE +21 -21
  4. data/Rakefile +13 -4
  5. data/bin/waitress +22 -22
  6. data/ext/Thanks.md +1 -1
  7. data/ext/waitress_http11/ext_help.h +15 -15
  8. data/ext/waitress_http11/extconf.rb +6 -6
  9. data/ext/waitress_http11/http11.c +532 -532
  10. data/ext/waitress_http11/http11_parser.c +1216 -1216
  11. data/ext/waitress_http11/http11_parser.h +49 -49
  12. data/ext/waitress_http11/http11_parser.java.rl +171 -171
  13. data/ext/waitress_http11/http11_parser.rl +165 -165
  14. data/ext/waitress_http11/http11_parser_common.rl +55 -55
  15. data/ext/waitress_http11/http11_wrb_parser.h +83 -83
  16. data/lib/waitress/chef.rb +110 -110
  17. data/lib/waitress/configure.rb +116 -116
  18. data/lib/waitress/handlers/dirhandler.rb +39 -39
  19. data/lib/waitress/handlers/handler.rb +57 -57
  20. data/lib/waitress/handlers/handler404.rb +25 -25
  21. data/lib/waitress/handlers/libhandler.rb +58 -58
  22. data/lib/waitress/kernel.rb +182 -182
  23. data/lib/waitress/parse/query.rb +60 -60
  24. data/lib/waitress/request.rb +45 -45
  25. data/lib/waitress/resources/default_config.rb +52 -52
  26. data/lib/waitress/resources/http/404.html +18 -18
  27. data/lib/waitress/resources/http/css/hack.css +37 -37
  28. data/lib/waitress/resources/http/css/waitress.css +57 -57
  29. data/lib/waitress/resources/http/fonts/eot/latin/hack-bold-latin-webfont.eot +0 -0
  30. data/lib/waitress/resources/http/fonts/eot/latin/hack-bolditalic-latin-webfont.eot +0 -0
  31. data/lib/waitress/resources/http/fonts/eot/latin/hack-italic-latin-webfont.eot +0 -0
  32. data/lib/waitress/resources/http/fonts/eot/latin/hack-regular-latin-webfont.eot +0 -0
  33. data/lib/waitress/resources/http/fonts/svg/latin/hack-bold-latin-webfont.svg +240 -240
  34. data/lib/waitress/resources/http/fonts/svg/latin/hack-bolditalic-latin-webfont.svg +240 -240
  35. data/lib/waitress/resources/http/fonts/svg/latin/hack-italic-latin-webfont.svg +240 -240
  36. data/lib/waitress/resources/http/fonts/svg/latin/hack-regular-latin-webfont.svg +240 -240
  37. data/lib/waitress/resources/http/fonts/web-ttf/latin/hack-bold-latin-webfont.ttf +0 -0
  38. data/lib/waitress/resources/http/fonts/web-ttf/latin/hack-bolditalic-latin-webfont.ttf +0 -0
  39. data/lib/waitress/resources/http/fonts/web-ttf/latin/hack-italic-latin-webfont.ttf +0 -0
  40. data/lib/waitress/resources/http/fonts/web-ttf/latin/hack-regular-latin-webfont.ttf +0 -0
  41. data/lib/waitress/resources/http/fonts/woff/latin/hack-bold-latin-webfont.woff +0 -0
  42. data/lib/waitress/resources/http/fonts/woff/latin/hack-bolditalic-latin-webfont.woff +0 -0
  43. data/lib/waitress/resources/http/fonts/woff/latin/hack-italic-latin-webfont.woff +0 -0
  44. data/lib/waitress/resources/http/fonts/woff/latin/hack-regular-latin-webfont.woff +0 -0
  45. data/lib/waitress/resources/http/fonts/woff2/latin/hack-bold-latin-webfont.woff2 +0 -0
  46. data/lib/waitress/resources/http/fonts/woff2/latin/hack-bolditalic-latin-webfont.woff2 +0 -0
  47. data/lib/waitress/resources/http/fonts/woff2/latin/hack-italic-latin-webfont.woff2 +0 -0
  48. data/lib/waitress/resources/http/fonts/woff2/latin/hack-regular-latin-webfont.woff2 +0 -0
  49. data/lib/waitress/resources/http/img/404.png +0 -0
  50. data/lib/waitress/resources/http/index.html +15 -15
  51. data/lib/waitress/response.rb +104 -104
  52. data/lib/waitress/server.rb +126 -115
  53. data/lib/waitress/util.rb +707 -713
  54. data/lib/waitress/version.rb +3 -3
  55. data/lib/waitress/vhost.rb +217 -217
  56. data/lib/waitress.rb +98 -98
  57. data/lib/waitress_http11.bundle +0 -0
  58. data/waitress-core.gemspec +29 -27
  59. metadata +35 -7
  60. data/lib/waitress_http11.so +0 -0
@@ -1,165 +1,165 @@
1
- /**
2
- * Copyright (c) 2005 Zed A. Shaw
3
- * You can redistribute it and/or modify it under the same terms as Ruby.
4
- */
5
- #include "http11_parser.h"
6
- #include <stdio.h>
7
- #include <assert.h>
8
- #include <stdlib.h>
9
- #include <ctype.h>
10
- #include <string.h>
11
-
12
- /*
13
- * capitalizes all lower-case ASCII characters,
14
- * converts dashes to underscores.
15
- */
16
- static void snake_upcase_char(char *c)
17
- {
18
- if (*c >= 'a' && *c <= 'z')
19
- *c &= ~0x20;
20
- else if (*c == '-')
21
- *c = '_';
22
- }
23
-
24
- #define LEN(AT, FPC) (FPC - buffer - parser->AT)
25
- #define MARK(M,FPC) (parser->M = (FPC) - buffer)
26
- #define PTR_TO(F) (buffer + parser->F)
27
-
28
- /** Machine **/
29
-
30
- %%{
31
-
32
- machine http_parser;
33
-
34
- action mark {MARK(mark, fpc); }
35
-
36
-
37
- action start_field { MARK(field_start, fpc); }
38
- action snake_upcase_field { snake_upcase_char((char *)fpc); }
39
- action write_field {
40
- parser->field_len = LEN(field_start, fpc);
41
- }
42
-
43
- action start_value { MARK(mark, fpc); }
44
- action write_value {
45
- if(parser->http_field != NULL) {
46
- parser->http_field(parser->data, PTR_TO(field_start), parser->field_len, PTR_TO(mark), LEN(mark, fpc));
47
- }
48
- }
49
- action request_method {
50
- if(parser->request_method != NULL)
51
- parser->request_method(parser->data, PTR_TO(mark), LEN(mark, fpc));
52
- }
53
- action request_uri {
54
- if(parser->request_uri != NULL)
55
- parser->request_uri(parser->data, PTR_TO(mark), LEN(mark, fpc));
56
- }
57
- action fragment {
58
- if(parser->fragment != NULL)
59
- parser->fragment(parser->data, PTR_TO(mark), LEN(mark, fpc));
60
- }
61
-
62
- action start_query {MARK(query_start, fpc); }
63
- action query_string {
64
- if(parser->query_string != NULL)
65
- parser->query_string(parser->data, PTR_TO(query_start), LEN(query_start, fpc));
66
- }
67
-
68
- action http_version {
69
- if(parser->http_version != NULL)
70
- parser->http_version(parser->data, PTR_TO(mark), LEN(mark, fpc));
71
- }
72
-
73
- action request_path {
74
- if(parser->request_path != NULL)
75
- parser->request_path(parser->data, PTR_TO(mark), LEN(mark,fpc));
76
- }
77
-
78
- action done {
79
- parser->body_start = fpc - buffer + 1;
80
- if(parser->header_done != NULL)
81
- parser->header_done(parser->data, fpc + 1, pe - fpc - 1);
82
- fbreak;
83
- }
84
-
85
- include http_parser_common "http11_parser_common.rl";
86
-
87
- }%%
88
-
89
- /** Data **/
90
- %% write data;
91
-
92
- int http_parser_init(http_parser *parser) {
93
- int cs = 0;
94
- %% write init;
95
- parser->cs = cs;
96
- parser->body_start = 0;
97
- parser->content_len = 0;
98
- parser->mark = 0;
99
- parser->nread = 0;
100
- parser->field_len = 0;
101
- parser->field_start = 0;
102
-
103
- return(1);
104
- }
105
-
106
-
107
- /** exec **/
108
- size_t http_parser_execute(http_parser *parser, const char *buffer, size_t len, size_t off) {
109
- const char *p, *pe;
110
- int cs = parser->cs;
111
-
112
- assert(off <= len && "offset past end of buffer");
113
-
114
- p = buffer+off;
115
- pe = buffer+len;
116
-
117
- assert(*pe == '\0' && "pointer does not end on NUL");
118
- assert(pe - p == len - off && "pointers aren't same distance");
119
-
120
-
121
- %% write exec;
122
-
123
- parser->cs = cs;
124
- parser->nread += p - (buffer + off);
125
-
126
- assert(p <= pe && "buffer overflow after parsing execute");
127
- assert(parser->nread <= len && "nread longer than length");
128
- assert(parser->body_start <= len && "body starts after buffer end");
129
- assert(parser->mark < len && "mark is after buffer end");
130
- assert(parser->field_len <= len && "field has length longer than whole buffer");
131
- assert(parser->field_start < len && "field starts after buffer end");
132
-
133
- if(parser->body_start) {
134
- /* final \r\n combo encountered so stop right here */
135
- %%write eof;
136
- parser->nread++;
137
- }
138
-
139
- return(parser->nread);
140
- }
141
-
142
- int http_parser_finish(http_parser *parser)
143
- {
144
- int cs = parser->cs;
145
-
146
- %%write eof;
147
-
148
- parser->cs = cs;
149
-
150
- if (http_parser_has_error(parser) ) {
151
- return -1;
152
- } else if (http_parser_is_finished(parser) ) {
153
- return 1;
154
- } else {
155
- return 0;
156
- }
157
- }
158
-
159
- int http_parser_has_error(http_parser *parser) {
160
- return parser->cs == http_parser_error;
161
- }
162
-
163
- int http_parser_is_finished(http_parser *parser) {
164
- return parser->cs == http_parser_first_final;
165
- }
1
+ /**
2
+ * Copyright (c) 2005 Zed A. Shaw
3
+ * You can redistribute it and/or modify it under the same terms as Ruby.
4
+ */
5
+ #include "http11_parser.h"
6
+ #include <stdio.h>
7
+ #include <assert.h>
8
+ #include <stdlib.h>
9
+ #include <ctype.h>
10
+ #include <string.h>
11
+
12
+ /*
13
+ * capitalizes all lower-case ASCII characters,
14
+ * converts dashes to underscores.
15
+ */
16
+ static void snake_upcase_char(char *c)
17
+ {
18
+ if (*c >= 'a' && *c <= 'z')
19
+ *c &= ~0x20;
20
+ else if (*c == '-')
21
+ *c = '_';
22
+ }
23
+
24
+ #define LEN(AT, FPC) (FPC - buffer - parser->AT)
25
+ #define MARK(M,FPC) (parser->M = (FPC) - buffer)
26
+ #define PTR_TO(F) (buffer + parser->F)
27
+
28
+ /** Machine **/
29
+
30
+ %%{
31
+
32
+ machine http_parser;
33
+
34
+ action mark {MARK(mark, fpc); }
35
+
36
+
37
+ action start_field { MARK(field_start, fpc); }
38
+ action snake_upcase_field { snake_upcase_char((char *)fpc); }
39
+ action write_field {
40
+ parser->field_len = LEN(field_start, fpc);
41
+ }
42
+
43
+ action start_value { MARK(mark, fpc); }
44
+ action write_value {
45
+ if(parser->http_field != NULL) {
46
+ parser->http_field(parser->data, PTR_TO(field_start), parser->field_len, PTR_TO(mark), LEN(mark, fpc));
47
+ }
48
+ }
49
+ action request_method {
50
+ if(parser->request_method != NULL)
51
+ parser->request_method(parser->data, PTR_TO(mark), LEN(mark, fpc));
52
+ }
53
+ action request_uri {
54
+ if(parser->request_uri != NULL)
55
+ parser->request_uri(parser->data, PTR_TO(mark), LEN(mark, fpc));
56
+ }
57
+ action fragment {
58
+ if(parser->fragment != NULL)
59
+ parser->fragment(parser->data, PTR_TO(mark), LEN(mark, fpc));
60
+ }
61
+
62
+ action start_query {MARK(query_start, fpc); }
63
+ action query_string {
64
+ if(parser->query_string != NULL)
65
+ parser->query_string(parser->data, PTR_TO(query_start), LEN(query_start, fpc));
66
+ }
67
+
68
+ action http_version {
69
+ if(parser->http_version != NULL)
70
+ parser->http_version(parser->data, PTR_TO(mark), LEN(mark, fpc));
71
+ }
72
+
73
+ action request_path {
74
+ if(parser->request_path != NULL)
75
+ parser->request_path(parser->data, PTR_TO(mark), LEN(mark,fpc));
76
+ }
77
+
78
+ action done {
79
+ parser->body_start = fpc - buffer + 1;
80
+ if(parser->header_done != NULL)
81
+ parser->header_done(parser->data, fpc + 1, pe - fpc - 1);
82
+ fbreak;
83
+ }
84
+
85
+ include http_parser_common "http11_parser_common.rl";
86
+
87
+ }%%
88
+
89
+ /** Data **/
90
+ %% write data;
91
+
92
+ int http_parser_init(http_parser *parser) {
93
+ int cs = 0;
94
+ %% write init;
95
+ parser->cs = cs;
96
+ parser->body_start = 0;
97
+ parser->content_len = 0;
98
+ parser->mark = 0;
99
+ parser->nread = 0;
100
+ parser->field_len = 0;
101
+ parser->field_start = 0;
102
+
103
+ return(1);
104
+ }
105
+
106
+
107
+ /** exec **/
108
+ size_t http_parser_execute(http_parser *parser, const char *buffer, size_t len, size_t off) {
109
+ const char *p, *pe;
110
+ int cs = parser->cs;
111
+
112
+ assert(off <= len && "offset past end of buffer");
113
+
114
+ p = buffer+off;
115
+ pe = buffer+len;
116
+
117
+ assert(*pe == '\0' && "pointer does not end on NUL");
118
+ assert(pe - p == len - off && "pointers aren't same distance");
119
+
120
+
121
+ %% write exec;
122
+
123
+ parser->cs = cs;
124
+ parser->nread += p - (buffer + off);
125
+
126
+ assert(p <= pe && "buffer overflow after parsing execute");
127
+ assert(parser->nread <= len && "nread longer than length");
128
+ assert(parser->body_start <= len && "body starts after buffer end");
129
+ assert(parser->mark < len && "mark is after buffer end");
130
+ assert(parser->field_len <= len && "field has length longer than whole buffer");
131
+ assert(parser->field_start < len && "field starts after buffer end");
132
+
133
+ if(parser->body_start) {
134
+ /* final \r\n combo encountered so stop right here */
135
+ %%write eof;
136
+ parser->nread++;
137
+ }
138
+
139
+ return(parser->nread);
140
+ }
141
+
142
+ int http_parser_finish(http_parser *parser)
143
+ {
144
+ int cs = parser->cs;
145
+
146
+ %%write eof;
147
+
148
+ parser->cs = cs;
149
+
150
+ if (http_parser_has_error(parser) ) {
151
+ return -1;
152
+ } else if (http_parser_is_finished(parser) ) {
153
+ return 1;
154
+ } else {
155
+ return 0;
156
+ }
157
+ }
158
+
159
+ int http_parser_has_error(http_parser *parser) {
160
+ return parser->cs == http_parser_error;
161
+ }
162
+
163
+ int http_parser_is_finished(http_parser *parser) {
164
+ return parser->cs == http_parser_first_final;
165
+ }
@@ -1,55 +1,55 @@
1
- %%{
2
-
3
- machine http_parser_common;
4
-
5
- #### HTTP PROTOCOL GRAMMAR
6
- # line endings
7
- CRLF = "\r\n";
8
-
9
- # character types
10
- CTL = (cntrl | 127);
11
- safe = ("$" | "-" | "_" | ".");
12
- extra = ("!" | "*" | "'" | "(" | ")" | ",");
13
- reserved = (";" | "/" | "?" | ":" | "@" | "&" | "=" | "+");
14
- sorta_safe = ("\"" | "<" | ">");
15
- unsafe = (CTL | " " | "#" | "%" | sorta_safe);
16
- national = any -- (alpha | digit | reserved | extra | safe | unsafe);
17
- unreserved = (alpha | digit | safe | extra | national);
18
- escape = ("%" xdigit xdigit);
19
- uchar = (unreserved | escape | sorta_safe);
20
- pchar = (uchar | ":" | "@" | "&" | "=" | "+");
21
- tspecials = ("(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\\" | "\"" | "/" | "[" | "]" | "?" | "=" | "{" | "}" | " " | "\t");
22
-
23
- # elements
24
- token = (ascii -- (CTL | tspecials));
25
-
26
- # URI schemes and absolute paths
27
- scheme = ( alpha | digit | "+" | "-" | "." )* ;
28
- absolute_uri = (scheme ":" (uchar | reserved )*);
29
-
30
- path = ( pchar+ ( "/" pchar* )* ) ;
31
- query = ( uchar | reserved )* %query_string ;
32
- param = ( pchar | "/" )* ;
33
- params = ( param ( ";" param )* ) ;
34
- rel_path = ( path? %request_path (";" params)? ) ("?" %start_query query)?;
35
- absolute_path = ( "/"+ rel_path );
36
-
37
- Request_URI = ( "*" | absolute_uri | absolute_path ) >mark %request_uri;
38
- Fragment = ( uchar | reserved )* >mark %fragment;
39
- Method = ( upper | digit | safe ){1,20} >mark %request_method;
40
-
41
- http_number = ( digit+ "." digit+ ) ;
42
- HTTP_Version = ( "HTTP/" http_number ) >mark %http_version ;
43
- Request_Line = ( Method " " Request_URI ("#" Fragment){0,1} " " HTTP_Version CRLF ) ;
44
-
45
- field_name = ( token -- ":" )+ >start_field $snake_upcase_field %write_field;
46
-
47
- field_value = any* >start_value %write_value;
48
-
49
- message_header = field_name ":" " "* field_value :> CRLF;
50
-
51
- Request = Request_Line ( message_header )* ( CRLF @done );
52
-
53
- main := Request;
54
-
55
- }%%
1
+ %%{
2
+
3
+ machine http_parser_common;
4
+
5
+ #### HTTP PROTOCOL GRAMMAR
6
+ # line endings
7
+ CRLF = "\r\n";
8
+
9
+ # character types
10
+ CTL = (cntrl | 127);
11
+ safe = ("$" | "-" | "_" | ".");
12
+ extra = ("!" | "*" | "'" | "(" | ")" | ",");
13
+ reserved = (";" | "/" | "?" | ":" | "@" | "&" | "=" | "+");
14
+ sorta_safe = ("\"" | "<" | ">");
15
+ unsafe = (CTL | " " | "#" | "%" | sorta_safe);
16
+ national = any -- (alpha | digit | reserved | extra | safe | unsafe);
17
+ unreserved = (alpha | digit | safe | extra | national);
18
+ escape = ("%" xdigit xdigit);
19
+ uchar = (unreserved | escape | sorta_safe);
20
+ pchar = (uchar | ":" | "@" | "&" | "=" | "+");
21
+ tspecials = ("(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\\" | "\"" | "/" | "[" | "]" | "?" | "=" | "{" | "}" | " " | "\t");
22
+
23
+ # elements
24
+ token = (ascii -- (CTL | tspecials));
25
+
26
+ # URI schemes and absolute paths
27
+ scheme = ( alpha | digit | "+" | "-" | "." )* ;
28
+ absolute_uri = (scheme ":" (uchar | reserved )*);
29
+
30
+ path = ( pchar+ ( "/" pchar* )* ) ;
31
+ query = ( uchar | reserved )* %query_string ;
32
+ param = ( pchar | "/" )* ;
33
+ params = ( param ( ";" param )* ) ;
34
+ rel_path = ( path? %request_path (";" params)? ) ("?" %start_query query)?;
35
+ absolute_path = ( "/"+ rel_path );
36
+
37
+ Request_URI = ( "*" | absolute_uri | absolute_path ) >mark %request_uri;
38
+ Fragment = ( uchar | reserved )* >mark %fragment;
39
+ Method = ( upper | digit | safe ){1,20} >mark %request_method;
40
+
41
+ http_number = ( digit+ "." digit+ ) ;
42
+ HTTP_Version = ( "HTTP/" http_number ) >mark %http_version ;
43
+ Request_Line = ( Method " " Request_URI ("#" Fragment){0,1} " " HTTP_Version CRLF ) ;
44
+
45
+ field_name = ( token -- ":" )+ >start_field $snake_upcase_field %write_field;
46
+
47
+ field_value = any* >start_value %write_value;
48
+
49
+ message_header = field_name ":" " "* field_value :> CRLF;
50
+
51
+ Request = Request_Line ( message_header )* ( CRLF @done );
52
+
53
+ main := Request;
54
+
55
+ }%%
@@ -1,83 +1,83 @@
1
- #ifndef RSTRING_PTR
2
- #define RSTRING_PTR(s) (RSTRING(s)->ptr)
3
- #endif
4
- #ifndef RSTRING_LEN
5
- #define RSTRING_LEN(s) (RSTRING(s)->len)
6
- #endif
7
-
8
- char *substr(const char *buff, int start, int len) {
9
- char subbuff[len + 1];
10
- memcpy(subbuff, &buff[start], len);
11
- subbuff[len] = '\0';
12
- return strdup(subbuff);
13
- }
14
-
15
- int mat(char *str1, char *str2) {
16
- return strcmp(str1, str2) == 0;
17
- }
18
-
19
- VALUE WRB_Parse(VALUE self, VALUE string, VALUE buffer) {
20
- char *sptr = RSTRING_PTR(string);
21
- long slen = RSTRING_LEN(string);
22
-
23
- char *tar = "<?ruby";
24
- char tarlen = 6;
25
- char *end = "?>";
26
- char endlen = 2;
27
-
28
- int i = 0;
29
- char pc = NULL;
30
- while (i < slen) {
31
- char c = sptr[i];
32
- int open_e = i + tarlen;
33
- char *open_s = substr(sptr, i, tarlen);
34
-
35
- if (mat(open_s, tar) && pc != '\\') {
36
- int j = open_e;
37
- int search = 1;
38
- int q1 = 0; int q2 = 0;
39
- while (j < slen && search) {
40
- char cc = sptr[j];
41
- int close_e = j + endlen;
42
- char *close_s = substr(sptr, j, endlen);
43
-
44
- if (sptr[j-1] != '\\') {
45
- if (cc == '\"') q1 = (q1 == 0 ? 1 : 0);
46
- if (cc == '\'') q2 = (q2 == 0 ? 1 : 0);
47
- if (mat(close_s, end) && !q1 && !q2) {
48
- i = close_e - 1;
49
- search = 0;
50
- char *rb_ev = substr(sptr, open_e, j - open_e);
51
- rb_eval_string(rb_ev);
52
- }
53
- }
54
-
55
- j+=1;
56
- }
57
-
58
- if (j == slen && search) {
59
- char *rb_ev = substr(sptr, open_e, j);
60
- i = slen;
61
- rb_eval_string(rb_ev);
62
- }
63
- } else if (c == '\\') {
64
- if (!mat(substr(sptr, i+1, tarlen), tar)) {
65
- char strbuf[2] = "\0";
66
- strbuf[0] = c;
67
- rb_funcall(buffer, rb_intern("write"), 1, rb_str_new2(strbuf));
68
- }
69
- } else {
70
- char strbuf[2] = "\0";
71
- strbuf[0] = c;
72
- rb_funcall(buffer, rb_intern("write"), 1, rb_str_new2(strbuf));
73
- }
74
-
75
- pc = c;
76
- i += 1;
77
- }
78
- }
79
-
80
- void init_parse(VALUE rubyModule) {
81
- VALUE cWaParse = rb_define_class_under(rubyModule, "WRBParser", rb_cObject);
82
- rb_define_module_function(cWaParse, "parse!", WRB_Parse, 2);
83
- }
1
+ #ifndef RSTRING_PTR
2
+ #define RSTRING_PTR(s) (RSTRING(s)->ptr)
3
+ #endif
4
+ #ifndef RSTRING_LEN
5
+ #define RSTRING_LEN(s) (RSTRING(s)->len)
6
+ #endif
7
+
8
+ char *substr(const char *buff, int start, int len) {
9
+ char subbuff[len + 1];
10
+ memcpy(subbuff, &buff[start], len);
11
+ subbuff[len] = '\0';
12
+ return strdup(subbuff);
13
+ }
14
+
15
+ int mat(char *str1, char *str2) {
16
+ return strcmp(str1, str2) == 0;
17
+ }
18
+
19
+ VALUE WRB_Parse(VALUE self, VALUE string, VALUE buffer) {
20
+ char *sptr = RSTRING_PTR(string);
21
+ long slen = RSTRING_LEN(string);
22
+
23
+ char *tar = "<?ruby";
24
+ char tarlen = 6;
25
+ char *end = "?>";
26
+ char endlen = 2;
27
+
28
+ int i = 0;
29
+ char pc = NULL;
30
+ while (i < slen) {
31
+ char c = sptr[i];
32
+ int open_e = i + tarlen;
33
+ char *open_s = substr(sptr, i, tarlen);
34
+
35
+ if (mat(open_s, tar) && pc != '\\') {
36
+ int j = open_e;
37
+ int search = 1;
38
+ int q1 = 0; int q2 = 0;
39
+ while (j < slen && search) {
40
+ char cc = sptr[j];
41
+ int close_e = j + endlen;
42
+ char *close_s = substr(sptr, j, endlen);
43
+
44
+ if (sptr[j-1] != '\\') {
45
+ if (cc == '\"') q1 = (q1 == 0 ? 1 : 0);
46
+ if (cc == '\'') q2 = (q2 == 0 ? 1 : 0);
47
+ if (mat(close_s, end) && !q1 && !q2) {
48
+ i = close_e - 1;
49
+ search = 0;
50
+ char *rb_ev = substr(sptr, open_e, j - open_e);
51
+ rb_eval_string(rb_ev);
52
+ }
53
+ }
54
+
55
+ j+=1;
56
+ }
57
+
58
+ if (j == slen && search) {
59
+ char *rb_ev = substr(sptr, open_e, j);
60
+ i = slen;
61
+ rb_eval_string(rb_ev);
62
+ }
63
+ } else if (c == '\\') {
64
+ if (!mat(substr(sptr, i+1, tarlen), tar)) {
65
+ char strbuf[2] = "\0";
66
+ strbuf[0] = c;
67
+ rb_funcall(buffer, rb_intern("write"), 1, rb_str_new2(strbuf));
68
+ }
69
+ } else {
70
+ char strbuf[2] = "\0";
71
+ strbuf[0] = c;
72
+ rb_funcall(buffer, rb_intern("write"), 1, rb_str_new2(strbuf));
73
+ }
74
+
75
+ pc = c;
76
+ i += 1;
77
+ }
78
+ }
79
+
80
+ void init_parse(VALUE rubyModule) {
81
+ VALUE cWaParse = rb_define_class_under(rubyModule, "WRBParser", rb_cObject);
82
+ rb_define_module_function(cWaParse, "parse!", WRB_Parse, 2);
83
+ }