qr_reader-native 0.0.1

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 (95) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE-mruby.txt +22 -0
  3. data/LICENSE-spinel.txt +19 -0
  4. data/LICENSE.txt +21 -0
  5. data/README.md +61 -0
  6. data/ext/qr_reader_native/SPINEL_VERSION +1 -0
  7. data/ext/qr_reader_native/extconf.rb +8 -0
  8. data/ext/qr_reader_native/mruby/error.h +13 -0
  9. data/ext/qr_reader_native/mruby/internal.h +145 -0
  10. data/ext/qr_reader_native/mruby/string.h +22 -0
  11. data/ext/qr_reader_native/mruby.h +93 -0
  12. data/ext/qr_reader_native/mruby_shim.h +118 -0
  13. data/ext/qr_reader_native/qr_reader_native.c +13513 -0
  14. data/ext/qr_reader_native/qr_reader_native.h +29 -0
  15. data/ext/qr_reader_native/qr_reader_native_ext.c +598 -0
  16. data/ext/qr_reader_native/re_cased.h +71 -0
  17. data/ext/qr_reader_native/re_compile.c +5784 -0
  18. data/ext/qr_reader_native/re_ctype.h +3540 -0
  19. data/ext/qr_reader_native/re_exec.c +2190 -0
  20. data/ext/qr_reader_native/re_internal.h +671 -0
  21. data/ext/qr_reader_native/re_prop.h +4629 -0
  22. data/ext/qr_reader_native/re_spinel.c +363 -0
  23. data/ext/qr_reader_native/re_spinel.h +22 -0
  24. data/ext/qr_reader_native/re_spinel_utf8.inc +97 -0
  25. data/ext/qr_reader_native/re_utf8.c +156 -0
  26. data/ext/qr_reader_native/sp_alloc.c +1447 -0
  27. data/ext/qr_reader_native/sp_alloc.h +1196 -0
  28. data/ext/qr_reader_native/sp_argf.h +33 -0
  29. data/ext/qr_reader_native/sp_array.c +1052 -0
  30. data/ext/qr_reader_native/sp_array.h +456 -0
  31. data/ext/qr_reader_native/sp_bigint.c +5826 -0
  32. data/ext/qr_reader_native/sp_bigint.h +117 -0
  33. data/ext/qr_reader_native/sp_cold.c +5259 -0
  34. data/ext/qr_reader_native/sp_compat.h +402 -0
  35. data/ext/qr_reader_native/sp_core.c +818 -0
  36. data/ext/qr_reader_native/sp_core.h +56 -0
  37. data/ext/qr_reader_native/sp_crypto.c +877 -0
  38. data/ext/qr_reader_native/sp_crypto.h +169 -0
  39. data/ext/qr_reader_native/sp_dtoa.c +1533 -0
  40. data/ext/qr_reader_native/sp_dtoa.h +29 -0
  41. data/ext/qr_reader_native/sp_encoding_names.h +172 -0
  42. data/ext/qr_reader_native/sp_enum.h +86 -0
  43. data/ext/qr_reader_native/sp_exc.c +1185 -0
  44. data/ext/qr_reader_native/sp_exc.h +186 -0
  45. data/ext/qr_reader_native/sp_exc_ctx.h +56 -0
  46. data/ext/qr_reader_native/sp_fiber.c +889 -0
  47. data/ext/qr_reader_native/sp_fiber.h +162 -0
  48. data/ext/qr_reader_native/sp_fiber_ctx.h +84 -0
  49. data/ext/qr_reader_native/sp_format.c +695 -0
  50. data/ext/qr_reader_native/sp_format.h +83 -0
  51. data/ext/qr_reader_native/sp_gc.c +1793 -0
  52. data/ext/qr_reader_native/sp_gc.h +762 -0
  53. data/ext/qr_reader_native/sp_hash.c +131 -0
  54. data/ext/qr_reader_native/sp_hash.h +131 -0
  55. data/ext/qr_reader_native/sp_inspect.c +215 -0
  56. data/ext/qr_reader_native/sp_inspect.h +128 -0
  57. data/ext/qr_reader_native/sp_io.c +1676 -0
  58. data/ext/qr_reader_native/sp_io.h +272 -0
  59. data/ext/qr_reader_native/sp_iobuffer.c +1014 -0
  60. data/ext/qr_reader_native/sp_iobuffer.h +167 -0
  61. data/ext/qr_reader_native/sp_marshal.c +487 -0
  62. data/ext/qr_reader_native/sp_marshal.h +60 -0
  63. data/ext/qr_reader_native/sp_net.c +1029 -0
  64. data/ext/qr_reader_native/sp_net.h +205 -0
  65. data/ext/qr_reader_native/sp_pack.c +1254 -0
  66. data/ext/qr_reader_native/sp_poly_cold.c +1220 -0
  67. data/ext/qr_reader_native/sp_proc.c +410 -0
  68. data/ext/qr_reader_native/sp_proc.h +327 -0
  69. data/ext/qr_reader_native/sp_process.c +547 -0
  70. data/ext/qr_reader_native/sp_process_status.c +211 -0
  71. data/ext/qr_reader_native/sp_process_status.h +66 -0
  72. data/ext/qr_reader_native/sp_random.c +287 -0
  73. data/ext/qr_reader_native/sp_random.h +52 -0
  74. data/ext/qr_reader_native/sp_range.h +144 -0
  75. data/ext/qr_reader_native/sp_re.c +1379 -0
  76. data/ext/qr_reader_native/sp_re.h +186 -0
  77. data/ext/qr_reader_native/sp_re_names.h +59 -0
  78. data/ext/qr_reader_native/sp_sched.c +4044 -0
  79. data/ext/qr_reader_native/sp_sched.h +295 -0
  80. data/ext/qr_reader_native/sp_slab.c +1507 -0
  81. data/ext/qr_reader_native/sp_str.c +1462 -0
  82. data/ext/qr_reader_native/sp_str.h +306 -0
  83. data/ext/qr_reader_native/sp_str_crypt.c +23 -0
  84. data/ext/qr_reader_native/sp_string.c +92 -0
  85. data/ext/qr_reader_native/sp_string.h +253 -0
  86. data/ext/qr_reader_native/sp_system.c +78 -0
  87. data/ext/qr_reader_native/sp_system.h +18 -0
  88. data/ext/qr_reader_native/sp_time.c +860 -0
  89. data/ext/qr_reader_native/sp_time.h +100 -0
  90. data/ext/qr_reader_native/sp_types.h +292 -0
  91. data/ext/qr_reader_native/spinel_rt.h +19017 -0
  92. data/ext/qr_reader_native/unicase.c +399 -0
  93. data/ext/qr_reader_native/unicase.h +901 -0
  94. data/lib/qr_reader/native.rb +6 -0
  95. metadata +153 -0
@@ -0,0 +1,272 @@
1
+ /* sp_io.h -- File / IO handle surface.
2
+ *
3
+ * sp_File is a stdio FILE* plus its (GC-managed) path/mode strings,
4
+ * shared between the generated translation unit and lib/sp_io.c, which
5
+ * holds the allocation-free handle ops. The string-returning readers
6
+ * (sp_File_gets / _read / _read_n / _path) stay inline in spinel_rt.h
7
+ * because they allocate via the hot static sp_str_alloc; moving them
8
+ * would split the per-TU string heap. */
9
+ #ifndef SP_IO_H
10
+ #define SP_IO_H
11
+
12
+ #include <stdio.h>
13
+ #include "sp_types.h" /* sp_int, sp_bool */
14
+ #include "sp_array.h" /* sp_IntArray (for #winsize) */
15
+
16
+ typedef struct {
17
+ FILE *fp; const char *path; const char *mode; sp_int lineno;
18
+ unsigned char bin_flag; /* #binmode was called (#3131) */
19
+ unsigned char no_autoclose; /* #autoclose = false (#3131) */
20
+ unsigned char is_sock; /* a socket handle: writes bypass stdio (#2922) */
21
+ unsigned char rev_lookup; /* a socket's #do_not_reverse_lookup is false:
22
+ addr / peeraddr report the host name. Taken
23
+ from the class setting when it is made */
24
+ unsigned char sync_on; /* #sync is true for this handle: a write reaches
25
+ the descriptor at once. A socket is always
26
+ sync (its writes bypass stdio); IO.pipe's
27
+ WRITE end is sync in CRuby too, and without
28
+ the flag a byte sat in stdio where a reader
29
+ -- or an IO.select on the other end -- could
30
+ not see it (#4263). */
31
+ unsigned char frozen; /* Object#freeze; kept here, not in the GC header,
32
+ because the standard streams are static storage
33
+ with no header to flip (sp_io_stdout) */
34
+ unsigned char wnonblock; /* write side of this handle is O_NONBLOCK:
35
+ 0 not asked, 1 yes, 2 could not (#4307) */
36
+ unsigned char wstream; /* SOCK_STREAM, asked once: 0 not yet, 1 yes,
37
+ 2 no. Only a byte stream may have a write
38
+ split at the send buffer's free space; on a
39
+ datagram socket each send IS one message */
40
+ unsigned char park; /* readiness-park kind, computed on the first
41
+ read: 0 not yet asked, 1 never (a regular
42
+ file is always ready), 2 park before a read
43
+ that could block (#4307) */
44
+ unsigned char closed; /* #close ran. The FILE the handle then carries
45
+ is the shared /dev/null sentinel, never the
46
+ freed one: a thread mid-read when another
47
+ closes the handle reads EOF from it instead
48
+ of dereferencing NULL or the next accept's
49
+ descriptor; every entry point tests this
50
+ flag (SP_IO_OPEN) and the parks re-test it
51
+ on the way back (#4546) */
52
+ unsigned char is_file; /* opened by File.open / File.new (a path the
53
+ program named): the handle is a File, and
54
+ answers the names Integer-sized files own
55
+ and IO does not -- #size, #truncate. A
56
+ pipe end, a socket, IO.for_fd, popen and
57
+ the standard streams are IO, whatever
58
+ path string they carry (#4706) */
59
+ int fno_plus1; /* IO.for_fd(fd, autoclose: false) wraps a dup(2)
60
+ of fd so close/fin never touch the caller's
61
+ descriptor; this carries the ORIGINAL fd (+1,
62
+ 0 = unset) so #fileno answers it (#4208) */
63
+ } sp_File;
64
+
65
+ /* Object#frozen? / #freeze on a handle. A nil slot is nil's answer: frozen. */
66
+ sp_bool sp_io_frozen(sp_File *f);
67
+ sp_File *sp_io_freeze(sp_File *f);
68
+ /* Object#== on two handles: identity, except that two File::Stat handles
69
+ compare as Comparable does for File::Stat -- by modification time. <=> reads
70
+ the same way (0 / nil, or the mtime order of two stats), boxed; to_s is
71
+ Object's #<Class:0xADDR> under the class the handle presents as. */
72
+ sp_bool sp_io_eq(sp_File *a, sp_File *b);
73
+ sp_RbVal sp_io_cmp(sp_File *a, sp_RbVal other);
74
+ const char *sp_io_to_s(sp_File *f);
75
+
76
+ /* File.open(path, mode) -> GC-managed handle (block form is codegen-only). */
77
+ sp_File *sp_File_open(const char *path, const char *mode);
78
+ /* pipe(2) wrapper. 0 ok, -1 error. */
79
+ int sp_io_make_pipe(int fds[2]);
80
+ /* IO.pipe end: wrap a raw pipe fd in a GC-managed sp_File. */
81
+ sp_File *sp_io_fdopen(int fd, const char *mode);
82
+ sp_File *sp_io_fdopen_ex(int fd, const char *mode, int owns_fd);
83
+ sp_File *sp_File_open_perm(const char *path, const char *mode, sp_int perm);
84
+ /* Wrap a connected/listening socket fd. Reads stay on the buffered FILE* so
85
+ #gets and friends work; writes bypass stdio straight to write(2), matching
86
+ CRuby sockets' sync = true. `kind` labels the handle ("tcp", "tcpserver",
87
+ ...) for #class rendering. (#2922) */
88
+ sp_File *sp_io_fdopen_sock(int fd, const char *kind);
89
+ void sp_io_wait_readable(sp_File *f);
90
+ void sp_io_wait_fd_readable(int fd);
91
+ /* Park until the handle can take bytes (a socket, or an IO.pipe write end). */
92
+ void sp_io_wait_writable(sp_File *f);
93
+ /* Bytes stdio already holds for this stream (readable without a read(2)). */
94
+ size_t sp_io_stdio_buffered(FILE *fp);
95
+ /* IO#read with no count on a handle whose read can block: fill to EOF,
96
+ parking between refills instead of sitting in the kernel (#4307). */
97
+ const char *sp_slurp_stream_parked(sp_File *f);
98
+ sp_int sp_File_write(sp_File *f, const char *s);
99
+ sp_int sp_File_write_bin(sp_File *f, const char *s);
100
+ sp_int sp_File_syswrite(sp_File *f, const char *s, size_t n);
101
+ sp_int sp_File_close(sp_File *f);
102
+
103
+ /* Every operation on a handle whose descriptor is gone raises IOError in
104
+ CRuby. Some of the read side already did; the write side and the position
105
+ queries answered a seed instead, so a write to a closed socket looked like
106
+ a successful send of zero bytes and the loss went unnoticed. The byte and
107
+ character readers, the flag accessors and the descriptor queries answered
108
+ nil, EOF or a default the same way, so a program that kept using a handle
109
+ it had closed ran on silently. #closed?, #close, #inspect and #path stay
110
+ exempt: they are the ones that are meant to work on a closed handle. The
111
+ metadata a File answers by its path (#size, #mtime, #chmod ...) still
112
+ answers here where CRuby raises: a File::Stat rides this same struct with
113
+ no descriptor, so that check cannot be this one. */
114
+ SP_NORETURN SP_COLD void sp_io_raise_closed(void);
115
+ #define SP_IO_OPEN(f) do { if (!(f) || !(f)->fp || (f)->closed) sp_io_raise_closed(); } while (0)
116
+ /* The FILE a closed handle carries (see sp_File.closed): /dev/null, opened once. */
117
+ FILE *sp_io_closed_sentinel(void);
118
+ sp_bool sp_File_closed_p(sp_File *f);
119
+ /* The handle flags codegen read straight off the struct (#lineno, #sync,
120
+ #autoclose? and their setters): through here so a closed handle answers
121
+ IOError for them too. #lineno= and #sync= answer their value, which is the
122
+ expression's; #autoclose='s emitter keeps its own operand. */
123
+ sp_int sp_File_lineno(sp_File *f);
124
+ sp_int sp_File_set_lineno(sp_File *f, sp_int n);
125
+ sp_bool sp_File_sync_p(sp_File *f);
126
+ sp_bool sp_File_set_sync(sp_File *f, sp_bool on);
127
+ sp_bool sp_File_autoclose_p(sp_File *f);
128
+ void sp_File_set_autoclose(sp_File *f, sp_bool on);
129
+ const char *sp_File_inspect(sp_File *f);
130
+ const char *sp_io_kind_name(sp_File *f);
131
+ sp_File *sp_sock_accept(sp_File *f);
132
+ sp_File *sp_sock_accept_nb(sp_File *f, sp_bool exc);
133
+ const char *sp_sock_read_nb(sp_File *f, sp_int len, sp_bool exc, sp_bool is_recv, sp_bool *eof);
134
+ sp_int sp_sock_write_nb(sp_File *f, const char *data, sp_bool exc);
135
+ sp_int sp_sock_write_nb_bin(sp_File *f, const char *data, sp_bool exc);
136
+ sp_int sp_sock_connect_nb(sp_File *f, const char *host, sp_int port, sp_bool exc);
137
+ /* Addrinfo-form connect_nonblock (already-resolved endpoint) */
138
+ sp_int sp_sock_connect_nb_sa(sp_File *f, const char *sa, sp_int salen,
139
+ sp_bool exc);
140
+ sp_bool sp_io_is_a(sp_File *f, const char *cls);
141
+ /* Of the reopened IO classes names[] (NULL-ended), the one nearest the
142
+ handle's kind up its class chain: its idx[] entry, or 0x7fffffff. */
143
+ int sp_io_pick_class(sp_File *f, const char *const *names, const int *idx);
144
+ sp_bool sp_io_instance_of(sp_File *f, const char *cls);
145
+ sp_File *sp_sock_udp_new(sp_int family);
146
+ const char *sp_sock_gethostname(void);
147
+ sp_int sp_sock_addrinfo_hint(sp_RbVal v, sp_int is_family);
148
+ sp_PolyArray *sp_sock_getaddrinfo(const char *host, sp_int port, sp_int family, sp_int socktype);
149
+ sp_Addrinfo *sp_sock_address(sp_File *f, sp_int peer);
150
+ /* BasicSocket.do_not_reverse_lookup (shared by every socket class) and the
151
+ per-socket flag a new socket takes from it */
152
+ extern sp_bool sp_sock_dnrl_default;
153
+ sp_bool sp_sock_dnrl(sp_File *f);
154
+ void sp_sock_set_dnrl(sp_File *f, sp_bool on);
155
+ /* Packed sockaddr strings: what Socket.sockaddr_in / Socket.pack_sockaddr_in,
156
+ Socket.pack_sockaddr_un and Addrinfo#to_sockaddr answer, and what the 1-arg
157
+ connect_nonblock takes. Byte strings -- they carry NUL. */
158
+ const char *sp_sock_pack_sockaddr_in(sp_int port, const char *host);
159
+ const char *sp_sock_pack_sockaddr_un(const char *path);
160
+ const char *sp_addrinfo_to_sockaddr(sp_Addrinfo *a);
161
+ sp_PolyArray *sp_sock_unpack_sockaddr_in(const char *sa);
162
+ sp_File *sp_sock_new(sp_int domain, sp_int type, sp_int proto);
163
+ sp_File *sp_sock_pair_end(sp_int domain, sp_int type, sp_int proto, sp_int which);
164
+ sp_File *sp_sock_unix_server(const char *path);
165
+ sp_File *sp_sock_unix_connect(const char *path);
166
+ sp_int sp_sock_bind(sp_File *f, const char *host, sp_int port);
167
+ sp_int sp_sock_connect(sp_File *f, const char *host, sp_int port);
168
+ sp_int sp_sock_send(sp_File *f, const char *data, sp_int len, const char *host, sp_int port);
169
+ sp_int sp_sock_shutdown(sp_File *f, sp_int how);
170
+ sp_int sp_sock_const(const char *n);
171
+ const char *sp_sock_recv(sp_File *f, sp_int len);
172
+ const char *sp_sock_recvfrom(sp_File *f, sp_int len, const char **ip_out, sp_int *port_out);
173
+ sp_int sp_sock_optval(sp_RbVal v);
174
+ sp_int sp_sock_setsockopt(sp_File *f, sp_int level, sp_int opt, sp_int value);
175
+ sp_SockOpt *sp_sock_getsockopt(sp_File *f, sp_int level, sp_int opt);
176
+ sp_int sp_sock_listen(sp_File *f, sp_int backlog);
177
+ void sp_File_puts(sp_File *f, const char *s);
178
+ void sp_File_puts_bin(sp_File *f, const char *s);
179
+ void sp_File_print(sp_File *f, const char *s);
180
+ sp_int sp_File_flush(sp_File *f);
181
+ sp_bool sp_File_eof_p(sp_File *f);
182
+ /* IO instance methods riding the underlying fd (#3038). */
183
+ sp_int sp_File_readbyte(sp_File *f);
184
+ void sp_File_ungetbyte(sp_File *f, sp_int byte);
185
+ sp_bool sp_File_binmode_p(sp_File *f);
186
+ void sp_File_set_binmode(sp_File *f);
187
+ sp_File *sp_File_reopen_io(sp_File *f, sp_File *other);
188
+ sp_bool sp_File_close_on_exec_p(sp_File *f);
189
+ void sp_File_set_close_on_exec(sp_File *f, sp_bool on);
190
+ sp_int sp_File_fcntl(sp_File *f, sp_int cmd, sp_int arg);
191
+ sp_int sp_File_pwrite(sp_File *f, const char *s, sp_int off);
192
+ sp_int sp_File_pwrite_bin(sp_File *f, const char *s, sp_int off);
193
+ void sp_File_advise(sp_File *f, const char *kind, sp_int off, sp_int len);
194
+ void sp_File_close_half(sp_File *f, sp_bool reading);
195
+ sp_File *sp_File_reopen(sp_File *f, const char *path, const char *mode);
196
+ sp_int sp_File_seek(sp_File *f, sp_int off, sp_int whence); /* #seek -- whence: 0=SET 1=CUR 2=END */
197
+ sp_int sp_File_tell(sp_File *f); /* #tell / #pos -- ftello, -1 on closed */
198
+ sp_int sp_File_rewind(sp_File *f); /* #rewind */
199
+ sp_bool sp_File_tty_p(sp_File *f); /* #tty? / #isatty -- isatty(fileno) */
200
+ sp_int sp_File_fileno(sp_File *f); /* #fileno */
201
+ sp_IntArray *sp_File_winsize(sp_File *f); /* #winsize -> [rows, cols] (ioctl, or [0,0]) */
202
+ sp_IntArray *sp_File_set_winsize(sp_File *f, sp_IntArray *size); /* #winsize= [rows, cols(, xpx, ypx)] (ioctl; Errno on a non-tty) */
203
+
204
+ /* STDOUT / STDERR as shared IO handles wrapping the C stdout/stderr streams.
205
+ The handle is a function-local static (stdout/stderr are not constant
206
+ initializers) and is never closed. */
207
+ sp_File *sp_io_stdout(void);
208
+ sp_File *sp_io_stderr(void);
209
+ sp_File *sp_io_stdin(void);
210
+
211
+ /* File metadata predicates (libc/WinAPI only; defined in sp_io.c). */
212
+ sp_bool sp_file_directory(const char *path);
213
+ sp_bool sp_file_file(const char *path);
214
+ sp_bool sp_file_exist(const char *path);
215
+ sp_bool sp_file_symlink(const char *path);
216
+ sp_bool sp_file_owned(const char *path);
217
+ sp_bool sp_file_grpowned(const char *path);
218
+ sp_bool sp_file_setuid(const char *path);
219
+ sp_bool sp_file_setgid(const char *path);
220
+ sp_bool sp_file_sticky(const char *path);
221
+ sp_bool sp_file_socket(const char *path);
222
+ sp_bool sp_file_blockdev(const char *path);
223
+ sp_bool sp_file_chardev(const char *path);
224
+ sp_int sp_file_world_readable(const char *path);
225
+ sp_int sp_file_world_writable(const char *path);
226
+ sp_int sp_file_do_symlink(const char *oldp, const char *newp);
227
+ sp_int sp_file_do_link(const char *oldp, const char *newp);
228
+ sp_int sp_file_umask(sp_int mask, int have_arg);
229
+ sp_int sp_file_mkfifo(const char *path, sp_int mode);
230
+ sp_int sp_file_utime_ns(int64_t asec, int32_t ansec, int64_t msec, int32_t mnsec, const char *path);
231
+ sp_int sp_file_lutime_ns(int64_t asec, int32_t ansec, int64_t msec, int32_t mnsec, const char *path);
232
+ const char *sp_file_readlink(const char *path); /* defined in sp_cold.c */
233
+ void sp_file_delete(const char *path);
234
+ void sp_file_rename(const char *from, const char *to);
235
+ /* A filesystem call that failed raises the Errno:: class CRuby raises for the
236
+ errno, with CRuby's message shape "<strerror> @ <op> - <path>". op is the
237
+ label after the @: for the File and Dir class methods it is CRuby's own
238
+ entry-point name (dir_s_mkdir, apply2files, rb_file_s_rename ...), so a
239
+ program matching on the text reads the same words; the socket calls and
240
+ the older File sites (readlink, symlink, mkfifo ...) pass the syscall's
241
+ name. An errno with no class here raises SystemCallError. */
242
+ SP_NORETURN void sp_file_raise_errno(const char *op, const char *path);
243
+ /* A nil path (a NULL string at run time) is CRuby's TypeError, raised before
244
+ any syscall sees it; the multi-path File.delete checks every path first. */
245
+ void sp_file_path_check(const char *path);
246
+
247
+ #include <dirent.h>
248
+ /* Dir handle (Dir.open / Dir.each_child ...): ops live in lib/sp_cold.c. */
249
+ typedef struct { DIR *dp; const char *path; } sp_Dir;
250
+ /* The Dir counterpart of SP_IO_OPEN: reading or positioning a closed handle
251
+ is IOError "closed directory" in CRuby; #close, #path and #inspect work. */
252
+ SP_NORETURN SP_COLD void sp_dir_raise_closed(void);
253
+ #define SP_DIR_OPEN(d) do { if (!(d) || !(d)->dp) sp_dir_raise_closed(); } while (0)
254
+
255
+ /* Object's to_s and <=> on the handle (sp_cold.c), declared here with the
256
+ struct because the poly to_s and spaceship in spinel_rt.h call them. */
257
+ const char *sp_Dir_to_s(sp_Dir *d);
258
+ sp_RbVal sp_Dir_cmp(sp_Dir *d, sp_RbVal other);
259
+
260
+ /* ---- sp_io_pipe/sysopen relocated from spinel_rt.h (0 optcarrot uses). ---- */
261
+ sp_PolyArray *sp_io_pipe(void);
262
+ sp_int sp_io_sysopen(const char *path, sp_int flags, sp_int perm);
263
+
264
+ /* IO.select accepts anything that answers #to_io, which is how CRuby lets a
265
+ wrapper -- a protocol object holding a socket -- be waited on. The runtime
266
+ cannot dispatch a user method itself, so codegen emits the cls_id switch and
267
+ main() installs it here, the same shape as sp_user_exc_parent_fn and the
268
+ sp_json_*_fn hooks. NULL when the program defines no #to_io, which is when
269
+ an element that is not an IO is the TypeError it always was. */
270
+ extern sp_File *(*sp_user_to_io_hook)(sp_RbVal);
271
+
272
+ #endif