Commit | Line | Data |
85982a32 |
1 | /* |
af1f55d9 |
2 | $Id: Encode.xs,v 1.38 2002/04/24 20:11:14 dankogai Exp dankogai $ |
85982a32 |
3 | */ |
4 | |
fcf2db38 |
5 | #define PERL_NO_GET_CONTEXT |
2c674647 |
6 | #include "EXTERN.h" |
7 | #include "perl.h" |
8 | #include "XSUB.h" |
2f2b4ff2 |
9 | #define U8 U8 |
10 | #include "encode.h" |
0ab8f81e |
11 | # define PERLIO_FILENAME "PerlIO/encoding.pm" |
aae85ceb |
12 | |
85982a32 |
13 | /* set 1 or more to profile. t/encoding.t dumps core because of |
14 | Perl_warner and PerlIO don't work well */ |
0ab8f81e |
15 | #define ENCODE_XS_PROFILE 0 |
39cf9a5e |
16 | |
85982a32 |
17 | /* set 0 to disable floating point to calculate buffer size for |
18 | encode_method(). 1 is recommended. 2 restores NI-S original */ |
0ab8f81e |
19 | #define ENCODE_XS_USEFP 1 |
39cf9a5e |
20 | |
fcf2db38 |
21 | #define UNIMPLEMENTED(x,y) y x (SV *sv, char *encoding) {dTHX; \ |
2f5768b8 |
22 | Perl_croak(aTHX_ "panic_unimplemented"); \ |
4a83738a |
23 | return (y)0; /* fool picky compilers */ \ |
87714904 |
24 | } |
85982a32 |
25 | /**/ |
011b2d2f |
26 | |
7e9a885a |
27 | UNIMPLEMENTED(_encoded_utf8_to_bytes, I32) |
28 | UNIMPLEMENTED(_encoded_bytes_to_utf8, I32) |
33af2bc7 |
29 | |
b0b300a3 |
30 | void |
aa0053b7 |
31 | Encode_XSEncoding(pTHX_ encode_t * enc) |
2f2b4ff2 |
32 | { |
aa0053b7 |
33 | dSP; |
34 | HV *stash = gv_stashpv("Encode::XS", TRUE); |
35 | SV *sv = sv_bless(newRV_noinc(newSViv(PTR2IV(enc))), stash); |
36 | int i = 0; |
37 | PUSHMARK(sp); |
38 | XPUSHs(sv); |
39 | while (enc->name[i]) { |
40 | const char *name = enc->name[i++]; |
41 | XPUSHs(sv_2mortal(newSVpvn(name, strlen(name)))); |
42 | } |
43 | PUTBACK; |
44 | call_pv("Encode::define_encoding", G_DISCARD); |
45 | SvREFCNT_dec(sv); |
2f2b4ff2 |
46 | } |
47 | |
aa0053b7 |
48 | void |
49 | call_failure(SV * routine, U8 * done, U8 * dest, U8 * orig) |
50 | { |
85982a32 |
51 | /* Exists for breakpointing */ |
aa0053b7 |
52 | } |
67e989fb |
53 | |
85982a32 |
54 | |
2f2b4ff2 |
55 | static SV * |
aa0053b7 |
56 | encode_method(pTHX_ encode_t * enc, encpage_t * dir, SV * src, |
85982a32 |
57 | int check) |
2f2b4ff2 |
58 | { |
aa0053b7 |
59 | STRLEN slen; |
60 | U8 *s = (U8 *) SvPV(src, slen); |
3aececda |
61 | STRLEN tlen = slen; |
62 | STRLEN ddone = 0; |
63 | STRLEN sdone = 0; |
39cf9a5e |
64 | |
3c49ab08 |
65 | /* We allocate slen+1. |
85982a32 |
66 | PerlIO dumps core if this value is smaller than this. */ |
3c49ab08 |
67 | SV *dst = sv_2mortal(newSV(slen+1)); |
85982a32 |
68 | U8 *d = (U8 *)SvPVX(dst); |
69 | STRLEN dlen = SvLEN(dst)-1; |
70 | int code; |
71 | |
72 | if (!slen){ |
73 | SvCUR_set(dst, 0); |
74 | SvPOK_only(dst); |
75 | goto ENCODE_END; |
76 | } |
77 | |
78 | while (code = do_encode(dir, s, &slen, d, dlen, &dlen, !check)) |
79 | { |
80 | SvCUR_set(dst, dlen+ddone); |
81 | SvPOK_only(dst); |
0b3236bb |
82 | |
85982a32 |
83 | if (code == ENCODE_FALLBACK || code == ENCODE_PARTIAL){ |
84 | break; |
85 | } |
86 | switch (code) { |
87 | case ENCODE_NOSPACE: |
88 | { |
89 | STRLEN more = 0; /* make sure you initialize! */ |
90 | STRLEN sleft; |
91 | sdone += slen; |
92 | ddone += dlen; |
93 | sleft = tlen - sdone; |
fcb875d4 |
94 | #if ENCODE_XS_PROFILE >= 2 |
85982a32 |
95 | Perl_warn(aTHX_ |
96 | "more=%d, sdone=%d, sleft=%d, SvLEN(dst)=%d\n", |
97 | more, sdone, sleft, SvLEN(dst)); |
fcb875d4 |
98 | #endif |
85982a32 |
99 | if (sdone != 0) { /* has src ever been processed ? */ |
39cf9a5e |
100 | #if ENCODE_XS_USEFP == 2 |
85982a32 |
101 | more = (1.0*tlen*SvLEN(dst)+sdone-1)/sdone |
102 | - SvLEN(dst); |
39cf9a5e |
103 | #elif ENCODE_XS_USEFP |
85982a32 |
104 | more = (1.0*SvLEN(dst)+1)/sdone * sleft; |
39cf9a5e |
105 | #else |
85982a32 |
106 | /* safe until SvLEN(dst) == MAX_INT/16 */ |
107 | more = (16*SvLEN(dst)+1)/sdone/16 * sleft; |
39cf9a5e |
108 | #endif |
39cf9a5e |
109 | } |
85982a32 |
110 | more += UTF8_MAXLEN; /* insurance policy */ |
111 | d = (U8 *) SvGROW(dst, SvLEN(dst) + more); |
112 | /* dst need to grow need MORE bytes! */ |
113 | if (ddone >= SvLEN(dst)) { |
114 | Perl_croak(aTHX_ "Destination couldn't be grown."); |
115 | } |
116 | dlen = SvLEN(dst)-ddone-1; |
117 | d += ddone; |
118 | s += slen; |
119 | slen = tlen-sdone; |
120 | continue; |
121 | } |
122 | case ENCODE_NOREP: |
123 | /* encoding */ |
0ab8f81e |
124 | if (dir == enc->f_utf8) { |
85982a32 |
125 | STRLEN clen; |
126 | UV ch = |
0ab8f81e |
127 | utf8n_to_uvuni(s+slen, (SvCUR(src)-slen), |
b0b300a3 |
128 | &clen, UTF8_ALLOW_ANY|UTF8_CHECK_ONLY); |
85982a32 |
129 | if (check & ENCODE_DIE_ON_ERR) { |
130 | Perl_croak( |
0ab8f81e |
131 | aTHX_ "\"\\N{U+%" UVxf "}\" does not map to %s, %d", |
85982a32 |
132 | ch, enc->name[0], __LINE__); |
133 | }else{ |
134 | if (check & ENCODE_RETURN_ON_ERR){ |
135 | if (check & ENCODE_WARN_ON_ERR){ |
136 | Perl_warner( |
137 | aTHX_ packWARN(WARN_UTF8), |
0ab8f81e |
138 | "\"\\N{U+%" UVxf "}\" does not map to %s", |
85982a32 |
139 | ch,enc->name[0]); |
140 | } |
141 | goto ENCODE_SET_SRC; |
142 | }else if (check & ENCODE_PERLQQ){ |
0ab8f81e |
143 | SV* perlqq = |
e4da7dce |
144 | sv_2mortal(newSVpvf("\\x{%04"UVxf"}", ch)); |
b2704119 |
145 | sdone += slen + clen; |
85982a32 |
146 | ddone += dlen + SvCUR(perlqq); |
147 | sv_catsv(dst, perlqq); |
af1f55d9 |
148 | }else if (check & ENCODE_HTMLCREF){ |
149 | SV* htmlcref = |
150 | sv_2mortal(newSVpvf("&#%d;", ch)); |
151 | sdone += slen + clen; |
152 | ddone += dlen + SvCUR(htmlcref); |
153 | sv_catsv(dst, htmlcref); |
154 | }else if (check & ENCODE_XMLCREF){ |
155 | SV* xmlcref = |
156 | sv_2mortal(newSVpvf("&#x%" UVxf ";", ch)); |
157 | sdone += slen + clen; |
158 | ddone += dlen + SvCUR(xmlcref); |
159 | sv_catsv(dst, xmlcref); |
0ab8f81e |
160 | } else { |
85982a32 |
161 | /* fallback char */ |
162 | sdone += slen + clen; |
0ab8f81e |
163 | ddone += dlen + enc->replen; |
164 | sv_catpvn(dst, (char*)enc->rep, enc->replen); |
b2704119 |
165 | } |
0ab8f81e |
166 | } |
b2704119 |
167 | } |
85982a32 |
168 | /* decoding */ |
0ab8f81e |
169 | else { |
85982a32 |
170 | if (check & ENCODE_DIE_ON_ERR){ |
171 | Perl_croak( |
172 | aTHX_ "%s \"\\x%02X\" does not map to Unicode (%d)", |
173 | enc->name[0], (U8) s[slen], code); |
174 | }else{ |
175 | if (check & ENCODE_RETURN_ON_ERR){ |
176 | if (check & ENCODE_WARN_ON_ERR){ |
177 | Perl_warner( |
178 | aTHX_ packWARN(WARN_UTF8), |
179 | "%s \"\\x%02X\" does not map to Unicode (%d)", |
180 | enc->name[0], (U8) s[slen], code); |
181 | } |
182 | goto ENCODE_SET_SRC; |
af1f55d9 |
183 | }else if (check & |
184 | (ENCODE_PERLQQ|ENCODE_HTMLCREF|ENCODE_XMLCREF)){ |
0ab8f81e |
185 | SV* perlqq = |
b2704119 |
186 | sv_2mortal(newSVpvf("\\x%02X", s[slen])); |
85982a32 |
187 | sdone += slen + 1; |
188 | ddone += dlen + SvCUR(perlqq); |
189 | sv_catsv(dst, perlqq); |
190 | } else { |
191 | sdone += slen + 1; |
0ab8f81e |
192 | ddone += dlen + strlen(FBCHAR_UTF8); |
193 | sv_catpv(dst, FBCHAR_UTF8); |
85982a32 |
194 | } |
aa0053b7 |
195 | } |
b2704119 |
196 | } |
85982a32 |
197 | /* settle variables when fallback */ |
b0b300a3 |
198 | d = (U8 *)SvEND(dst); |
0ab8f81e |
199 | dlen = SvLEN(dst) - ddone - 1; |
200 | s = (U8*)SvPVX(src) + sdone; |
b2704119 |
201 | slen = tlen - sdone; |
202 | break; |
2f2b4ff2 |
203 | |
85982a32 |
204 | default: |
205 | Perl_croak(aTHX_ "Unexpected code %d converting %s %s", |
206 | code, (dir == enc->f_utf8) ? "to" : "from", |
207 | enc->name[0]); |
208 | return &PL_sv_undef; |
aa0053b7 |
209 | } |
85982a32 |
210 | } |
211 | ENCODE_SET_SRC: |
6d1c0808 |
212 | if (check && !(check & ENCODE_LEAVE_SRC)){ |
213 | sdone = SvCUR(src) - (slen+sdone); |
85982a32 |
214 | if (sdone) { |
215 | sv_setpvn(src, (char*)s+slen, sdone); |
aa0053b7 |
216 | } |
85982a32 |
217 | SvCUR_set(src, sdone); |
2f2b4ff2 |
218 | } |
85982a32 |
219 | /* warn("check = 0x%X, code = 0x%d\n", check, code); */ |
220 | if (code && !(check & ENCODE_RETURN_ON_ERR)) { |
221 | return &PL_sv_undef; |
2f2b4ff2 |
222 | } |
0ab8f81e |
223 | |
85982a32 |
224 | SvCUR_set(dst, dlen+ddone); |
225 | SvPOK_only(dst); |
0ab8f81e |
226 | |
39cf9a5e |
227 | #if ENCODE_XS_PROFILE |
228 | if (SvCUR(dst) > SvCUR(src)){ |
85982a32 |
229 | Perl_warn(aTHX_ |
230 | "SvLEN(dst)=%d, SvCUR(dst)=%d. %d bytes unused(%f %%)\n", |
231 | SvLEN(dst), SvCUR(dst), SvLEN(dst) - SvCUR(dst), |
232 | (SvLEN(dst) - SvCUR(dst))*1.0/SvLEN(dst)*100.0); |
39cf9a5e |
233 | } |
3c49ab08 |
234 | #endif |
0ab8f81e |
235 | |
85982a32 |
236 | ENCODE_END: |
0b3236bb |
237 | *SvEND(dst) = '\0'; |
aa0053b7 |
238 | return dst; |
2f2b4ff2 |
239 | } |
240 | |
50d26985 |
241 | MODULE = Encode PACKAGE = Encode::XS PREFIX = Method_ |
2f2b4ff2 |
242 | |
243 | PROTOTYPES: ENABLE |
244 | |
245 | void |
0a95303c |
246 | Method_name(obj) |
247 | SV * obj |
248 | CODE: |
85982a32 |
249 | { |
250 | encode_t *enc = INT2PTR(encode_t *, SvIV(SvRV(obj))); |
251 | ST(0) = sv_2mortal(newSVpvn(enc->name[0],strlen(enc->name[0]))); |
252 | XSRETURN(1); |
253 | } |
0a95303c |
254 | |
255 | void |
b2704119 |
256 | Method_decode(obj,src,check = 0) |
2f2b4ff2 |
257 | SV * obj |
258 | SV * src |
b2704119 |
259 | int check |
2f2b4ff2 |
260 | CODE: |
aae85ceb |
261 | { |
85982a32 |
262 | encode_t *enc = INT2PTR(encode_t *, SvIV(SvRV(obj))); |
263 | ST(0) = encode_method(aTHX_ enc, enc->t_utf8, src, check); |
264 | SvUTF8_on(ST(0)); |
aae85ceb |
265 | XSRETURN(1); |
266 | } |
267 | |
268 | void |
85982a32 |
269 | Method_encode(obj,src,check = 0) |
aae85ceb |
270 | SV * obj |
85982a32 |
271 | SV * src |
272 | int check |
aae85ceb |
273 | CODE: |
274 | { |
85982a32 |
275 | encode_t *enc = INT2PTR(encode_t *, SvIV(SvRV(obj))); |
276 | sv_utf8_upgrade(src); |
277 | ST(0) = encode_method(aTHX_ enc, enc->f_utf8, src, check); |
aae85ceb |
278 | XSRETURN(1); |
279 | } |
280 | |
0ab8f81e |
281 | void |
282 | Method_needs_lines(obj) |
283 | SV * obj |
284 | CODE: |
285 | { |
286 | encode_t *enc = INT2PTR(encode_t *, SvIV(SvRV(obj))); |
287 | ST(0) = &PL_sv_no; |
288 | XSRETURN(1); |
289 | } |
290 | |
291 | void |
292 | Method_perlio_ok(obj) |
293 | SV * obj |
294 | CODE: |
295 | { |
296 | encode_t *enc = INT2PTR(encode_t *, SvIV(SvRV(obj))); |
011b2d2f |
297 | require_pv(PERLIO_FILENAME); |
0ab8f81e |
298 | if (hv_exists(get_hv("INC", 0), |
299 | PERLIO_FILENAME, strlen(PERLIO_FILENAME))) |
300 | { |
301 | ST(0) = &PL_sv_yes; |
302 | }else{ |
303 | ST(0) = &PL_sv_no; |
304 | } |
305 | XSRETURN(1); |
306 | } |
307 | |
67e989fb |
308 | MODULE = Encode PACKAGE = Encode |
2c674647 |
309 | |
310 | PROTOTYPES: ENABLE |
311 | |
67e989fb |
312 | I32 |
2c674647 |
313 | _bytes_to_utf8(sv, ...) |
85982a32 |
314 | SV * sv |
315 | CODE: |
316 | { |
317 | SV * encoding = items == 2 ? ST(1) : Nullsv; |
0ab8f81e |
318 | |
85982a32 |
319 | if (encoding) |
320 | RETVAL = _encoded_bytes_to_utf8(sv, SvPV_nolen(encoding)); |
321 | else { |
322 | STRLEN len; |
323 | U8* s = (U8*)SvPV(sv, len); |
324 | U8* converted; |
325 | |
326 | converted = bytes_to_utf8(s, &len); /* This allocs */ |
327 | sv_setpvn(sv, (char *)converted, len); |
328 | SvUTF8_on(sv); /* XXX Should we? */ |
329 | Safefree(converted); /* ... so free it */ |
330 | RETVAL = len; |
331 | } |
332 | } |
333 | OUTPUT: |
334 | RETVAL |
2c674647 |
335 | |
67e989fb |
336 | I32 |
2c674647 |
337 | _utf8_to_bytes(sv, ...) |
85982a32 |
338 | SV * sv |
339 | CODE: |
340 | { |
341 | SV * to = items > 1 ? ST(1) : Nullsv; |
342 | SV * check = items > 2 ? ST(2) : Nullsv; |
343 | |
344 | if (to) { |
345 | RETVAL = _encoded_utf8_to_bytes(sv, SvPV_nolen(to)); |
346 | } else { |
347 | STRLEN len; |
348 | U8 *s = (U8*)SvPV(sv, len); |
349 | |
350 | RETVAL = 0; |
351 | if (SvTRUE(check)) { |
352 | /* Must do things the slow way */ |
353 | U8 *dest; |
354 | /* We need a copy to pass to check() */ |
0ab8f81e |
355 | U8 *src = (U8*)savepv((char *)s); |
85982a32 |
356 | U8 *send = s + len; |
357 | |
358 | New(83, dest, len, U8); /* I think */ |
359 | |
360 | while (s < send) { |
361 | if (*s < 0x80){ |
362 | *dest++ = *s++; |
363 | } else { |
364 | STRLEN ulen; |
365 | UV uv = *s++; |
366 | |
367 | /* Have to do it all ourselves because of error routine, |
368 | aargh. */ |
369 | if (!(uv & 0x40)){ goto failure; } |
370 | if (!(uv & 0x20)) { ulen = 2; uv &= 0x1f; } |
371 | else if (!(uv & 0x10)) { ulen = 3; uv &= 0x0f; } |
372 | else if (!(uv & 0x08)) { ulen = 4; uv &= 0x07; } |
373 | else if (!(uv & 0x04)) { ulen = 5; uv &= 0x03; } |
374 | else if (!(uv & 0x02)) { ulen = 6; uv &= 0x01; } |
375 | else if (!(uv & 0x01)) { ulen = 7; uv = 0; } |
376 | else { ulen = 13; uv = 0; } |
87714904 |
377 | |
85982a32 |
378 | /* Note change to utf8.c variable naming, for variety */ |
379 | while (ulen--) { |
0ab8f81e |
380 | if ((*s & 0xc0) != 0x80){ |
381 | goto failure; |
85982a32 |
382 | } else { |
383 | uv = (uv << 6) | (*s++ & 0x3f); |
384 | } |
87714904 |
385 | } |
67e989fb |
386 | if (uv > 256) { |
387 | failure: |
85982a32 |
388 | call_failure(check, s, dest, src); |
389 | /* Now what happens? */ |
67e989fb |
390 | } |
391 | *dest++ = (U8)uv; |
85982a32 |
392 | } |
393 | } |
394 | } else { |
395 | RETVAL = (utf8_to_bytes(s, &len) ? len : 0); |
2c674647 |
396 | } |
85982a32 |
397 | } |
398 | } |
399 | OUTPUT: |
400 | RETVAL |
2c674647 |
401 | |
2c674647 |
402 | bool |
b2704119 |
403 | is_utf8(sv, check = 0) |
4411f3b6 |
404 | SV * sv |
b2704119 |
405 | int check |
85982a32 |
406 | CODE: |
407 | { |
408 | if (SvGMAGICAL(sv)) /* it could be $1, for example */ |
409 | sv = newSVsv(sv); /* GMAGIG will be done */ |
410 | if (SvPOK(sv)) { |
411 | RETVAL = SvUTF8(sv) ? TRUE : FALSE; |
412 | if (RETVAL && |
413 | check && |
414 | !is_utf8_string((U8*)SvPVX(sv), SvCUR(sv))) |
2c674647 |
415 | RETVAL = FALSE; |
85982a32 |
416 | } else { |
417 | RETVAL = FALSE; |
418 | } |
419 | if (sv != ST(0)) |
420 | SvREFCNT_dec(sv); /* it was a temp copy */ |
421 | } |
422 | OUTPUT: |
423 | RETVAL |
2c674647 |
424 | |
425 | SV * |
4411f3b6 |
426 | _utf8_on(sv) |
85982a32 |
427 | SV * sv |
428 | CODE: |
429 | { |
430 | if (SvPOK(sv)) { |
431 | SV *rsv = newSViv(SvUTF8(sv)); |
432 | RETVAL = rsv; |
433 | SvUTF8_on(sv); |
434 | } else { |
435 | RETVAL = &PL_sv_undef; |
436 | } |
437 | } |
438 | OUTPUT: |
439 | RETVAL |
2c674647 |
440 | |
441 | SV * |
4411f3b6 |
442 | _utf8_off(sv) |
85982a32 |
443 | SV * sv |
444 | CODE: |
445 | { |
446 | if (SvPOK(sv)) { |
447 | SV *rsv = newSViv(SvUTF8(sv)); |
448 | RETVAL = rsv; |
449 | SvUTF8_off(sv); |
450 | } else { |
451 | RETVAL = &PL_sv_undef; |
452 | } |
453 | } |
454 | OUTPUT: |
455 | RETVAL |
456 | |
85982a32 |
457 | int |
458 | DIE_ON_ERR() |
459 | CODE: |
460 | RETVAL = ENCODE_DIE_ON_ERR; |
461 | OUTPUT: |
462 | RETVAL |
463 | |
0ab8f81e |
464 | int |
85982a32 |
465 | WARN_ON_ERR() |
466 | CODE: |
467 | RETVAL = ENCODE_WARN_ON_ERR; |
468 | OUTPUT: |
469 | RETVAL |
470 | |
471 | int |
472 | LEAVE_SRC() |
473 | CODE: |
474 | RETVAL = ENCODE_LEAVE_SRC; |
475 | OUTPUT: |
476 | RETVAL |
477 | |
478 | int |
479 | RETURN_ON_ERR() |
480 | CODE: |
481 | RETVAL = ENCODE_RETURN_ON_ERR; |
482 | OUTPUT: |
483 | RETVAL |
484 | |
485 | int |
486 | PERLQQ() |
487 | CODE: |
488 | RETVAL = ENCODE_PERLQQ; |
489 | OUTPUT: |
490 | RETVAL |
491 | |
492 | int |
af1f55d9 |
493 | HTMLCREF() |
494 | CODE: |
495 | RETVAL = ENCODE_HTMLCREF; |
496 | OUTPUT: |
497 | RETVAL |
498 | |
499 | int |
500 | XMLCREF() |
501 | CODE: |
502 | RETVAL = ENCODE_XMLCREF; |
503 | OUTPUT: |
504 | RETVAL |
505 | |
506 | int |
85982a32 |
507 | FB_DEFAULT() |
508 | CODE: |
509 | RETVAL = ENCODE_FB_DEFAULT; |
510 | OUTPUT: |
511 | RETVAL |
512 | |
513 | int |
514 | FB_CROAK() |
515 | CODE: |
516 | RETVAL = ENCODE_FB_CROAK; |
517 | OUTPUT: |
518 | RETVAL |
519 | |
520 | int |
521 | FB_QUIET() |
522 | CODE: |
523 | RETVAL = ENCODE_FB_QUIET; |
524 | OUTPUT: |
525 | RETVAL |
526 | |
527 | int |
528 | FB_WARN() |
529 | CODE: |
530 | RETVAL = ENCODE_FB_WARN; |
531 | OUTPUT: |
532 | RETVAL |
533 | |
534 | int |
535 | FB_PERLQQ() |
536 | CODE: |
537 | RETVAL = ENCODE_FB_PERLQQ; |
538 | OUTPUT: |
539 | RETVAL |
2c674647 |
540 | |
af1f55d9 |
541 | int |
542 | FB_HTMLCREF() |
543 | CODE: |
544 | RETVAL = ENCODE_FB_HTMLCREF; |
545 | OUTPUT: |
546 | RETVAL |
547 | |
548 | int |
549 | FB_XMLCREF() |
550 | CODE: |
551 | RETVAL = ENCODE_FB_XMLCREF; |
552 | OUTPUT: |
553 | RETVAL |
554 | |
33af2bc7 |
555 | BOOT: |
556 | { |
85982a32 |
557 | #include "def_t.h" |
e7cbefb8 |
558 | #include "def_t.exh" |
33af2bc7 |
559 | } |