waitress-core 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
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
+ }