home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ruby164.zip / rbemx164.zip / ruby / share / doc / iconv-0.4.2 / iconv.c < prev    next >
C/C++ Source or Header  |  2000-09-23  |  22KB  |  849 lines

  1. /* -*- mode:c; c-file-style:"ruby" -*- */
  2. /*
  3. =begin
  4. = Summary
  5. Ruby extension for codeset conversion.
  6.  
  7. == License
  8.  $Revision: 0.4.2.0 $
  9.  $Copyleft: (c) 1999, 2000 Nobuyoshi.Nakada <nobu.nokada@softhome.net> $
  10.  
  11. This library is free software; you can redistribute it and/or
  12. modify it under the terms of
  13. ((<the GNU Lesser General Public License|URL:http://www.gnu.org/copyleft/lesser.txt>))
  14. as published by the Free Software Foundation; either
  15. version 2.1 of the License, or (at your option) any later version.
  16.  
  17. This library is distributed in the hope that it will be useful,
  18. but ((*WITHOUT ANY WARRANTY*)); without even the implied warranty of
  19. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
  20. ((<the GNU Lesser General Public License|URL:http://www.gnu.org/copyleft/lesser.txt>))
  21. for more details.
  22.  
  23. = Abstract
  24. Iconv is a wrapper class for UNIX 95 (({iconv()})) function family, which
  25. translates string between various coding systems.
  26.  
  27. See ((<Open Group|URL:http://www.opengroup.org/>))'s on-line documents for more details.
  28. * ((<iconv.h|URL:http://www.opengroup.org/onlinepubs/007908799/xsh/iconv.h.html>))
  29. * ((<iconv_open()|URL:http://www.opengroup.org/onlinepubs/007908799/xsh/iconv_open.html>))
  30. * ((<iconv()|URL:http://www.opengroup.org/onlinepubs/007908799/xsh/iconv.html>))
  31. * ((<iconv_close()|URL:http://www.opengroup.org/onlinepubs/007908799/xsh/iconv_close.html>))
  32.  
  33. Which coding systems are available, it depends on the platform.
  34.  
  35. =end
  36.  
  37. */
  38.  
  39. #include <errno.h>
  40. #include <iconv.h>
  41. #include <assert.h>
  42. #include "ruby.h"
  43. #include "intern.h"
  44.  
  45. static const char rcsid[] = "$Id: iconv.c,v 0.4.2.0 2000-09-23 18:03:19+09 nobu Exp $";
  46.  
  47. /* Invalid value for iconv_t is -1 but 0 for VALUE, I hope VALUE is
  48.    big enough to keep iconv_t */
  49. #define VALUE2ICONV(v) ((iconv_t)((VALUE)(v) ^ -1))
  50. #define ICONV2VALUE(c) ((VALUE)(c) ^ -1)
  51.  
  52. #ifndef HAVE_RB_BLOCK_GIVEN_P
  53. #define rb_block_given_p() rb_iterator_p()
  54. #endif
  55.  
  56. #ifdef HAVE_RB_OBJ_FREEZE
  57. #define STRING_FREEZE rb_obj_freeze
  58. #else
  59. #define STRING_FREEZE rb_str_freeze
  60. #endif
  61.  
  62. #ifndef OBJ_INFECT
  63. #define OBJ_INFECT(x,s) (void)(FL_ABLE(x) && FL_ABLE(s) && (RBASIC(x)->flags |= RBASIC(s)->flags & FL_TAINT))
  64. #endif
  65.  
  66. struct iconv_env_t
  67. {
  68.     iconv_t cd;
  69.     int argc;
  70.     VALUE *argv;
  71.     VALUE ret;
  72. };
  73.  
  74. static VALUE rb_eIconvFailure;
  75. static VALUE rb_eIconvIllegalSeq;
  76. static VALUE rb_eIconvInvalidChar;
  77. static VALUE rb_eIconvOutOfRange;
  78. static ID rb_inserter;
  79.  
  80. static ID rb_success, rb_failed, rb_mesg;
  81. static VALUE iconv_failure_success _((VALUE self));
  82. static VALUE iconv_failure_failed _((VALUE self));
  83. static VALUE iconv_finish _((VALUE self));
  84. static VALUE iconv_fail _((VALUE error, VALUE success, VALUE failed, struct iconv_env_t* env)) NORETURN;
  85.  
  86.  
  87. /*
  88. =begin
  89. = Classes & Modules
  90. =end
  91. */
  92.  
  93. /*
  94. =begin
  95. == Iconv
  96. =end
  97. */
  98. static iconv_t
  99. iconv_create
  100. #ifdef HAVE_PROTOTYPES
  101. (VALUE to, VALUE from)
  102. #else /* HAVE_PROTOTYPES */
  103.     (to, from)
  104.     VALUE to;
  105.     VALUE from;
  106. #endif /* HAVE_PROTOTYPES */
  107. {
  108.     const char* tocode = STR2CSTR(to);
  109.     const char* fromcode = STR2CSTR(from);
  110.     iconv_t cd = iconv_open(tocode, fromcode);
  111.  
  112.     if (cd == (iconv_t)-1) {
  113.     switch (errno) {
  114.       case EMFILE:
  115.       case ENFILE:
  116.       case ENOMEM:
  117.         rb_gc();
  118.         cd = iconv_open(tocode, fromcode);
  119.     }
  120.     if (cd == (iconv_t)-1) {
  121.         VALUE v[] = {
  122.         rb_str_new2("iconv(\"%s\", \"%s\")"), to, from,
  123.         };
  124.         rb_sys_fail(STR2CSTR(rb_f_sprintf(sizeof(v) / sizeof(v[0]), v)));
  125.     }
  126.     }
  127.  
  128.     return cd;
  129. }
  130.  
  131. static VALUE
  132. iconv_free
  133. #ifdef HAVE_PROTOTYPES
  134. (VALUE cd)
  135. #else /* HAVE_PROTOTYPES */
  136.     (cd)
  137.     VALUE cd;
  138. #endif /* HAVE_PROTOTYPES */
  139. {
  140.     if (cd && iconv_close(VALUE2ICONV(cd)) == -1)
  141.     rb_sys_fail("iconv_close");
  142.     return Qnil;
  143. }
  144. #ifdef RUBY_DATA_FUNC
  145. #define ICONV_FREE RUBY_DATA_FUNC(iconv_free)
  146. #elif defined(HAVE_RUBY_DATA_FUNC)
  147. #define ICONV_FREE (RUBY_DATA_FUNC)iconv_free
  148. #else  /* RUBY_DATA_FUNC: no way to know whether typedef'ed or not */
  149. #define ICONV_FREE (void (*)_((void*)))iconv_free
  150. #endif /* RUBY_DATA_FUNC */
  151.  
  152. static VALUE
  153. iconv_try
  154. #ifdef HAVE_PROTOTYPES
  155. (iconv_t cd, const char **inptr, size_t *inlen, char **outptr, size_t *outlen)
  156. #else /* HAVE_PROTOTYPES */
  157.     (cd, inptr, inlen, outptr, outlen)
  158.     iconv_t cd;
  159.     const char **inptr;
  160.     size_t *inlen;
  161.     char **outptr;
  162.     size_t *outlen;
  163. #endif /* HAVE_PROTOTYPES */
  164. {
  165.     if (iconv(cd, inptr, inlen, outptr, outlen) == (size_t)-1) {
  166.     switch (errno) {
  167.       case E2BIG:
  168.         /* try the left in next loop */
  169.         break;
  170.       case EILSEQ:
  171.         return rb_obj_alloc(rb_eIconvIllegalSeq);
  172.       case EINVAL:
  173.         return rb_obj_alloc(rb_eIconvInvalidChar);
  174.       default:
  175.         rb_sys_fail("iconv");
  176.     }
  177.     } else if (*inlen > 0) {
  178.     /* something goes wrong */
  179.     return rb_obj_alloc(rb_eIconvIllegalSeq);
  180.     }
  181.     return Qfalse;
  182. }
  183.  
  184. static VALUE
  185. iconv_fail
  186. #ifdef HAVE_PROTOTYPES
  187. (VALUE error, VALUE success, VALUE failed, struct iconv_env_t* env)
  188. #else /* HAVE_PROTOTYPES */
  189.     (error, success, failed, env)
  190.     VALUE error;
  191.     VALUE success;
  192.     VALUE failed;
  193.     struct iconv_env_t *env;
  194. #endif /* HAVE_PROTOTYPES */
  195. {
  196.     if (NIL_P(rb_ivar_get(error, rb_mesg)))
  197.     rb_ivar_set(error, rb_mesg, rb_inspect(failed));
  198.     if (env) {
  199.     success = rb_funcall3(env->ret, rb_inserter, 1, &success);
  200.     if (env->argc > 0) {
  201.         *(env->argv) = failed;
  202.         failed = rb_ary_new4(env->argc, env->argv);
  203.     }
  204.     }
  205.     rb_ivar_set(error, rb_success, success);
  206.     rb_ivar_set(error, rb_failed, failed);
  207.     rb_exc_raise(error);
  208. }
  209.  
  210. static VALUE
  211. rb_str_derive
  212. #ifdef HAVE_PROTOTYPES
  213. (VALUE str, const char* ptr, int len)
  214. #else /* HAVE_PROTOTYPES */
  215.     (str, ptr, len)
  216.     VALUE str;
  217.     const char *ptr;
  218.     int len;
  219. #endif /* HAVE_PROTOTYPES */
  220. {
  221.     VALUE ret;
  222.  
  223.     if (NIL_P(str))
  224.     return rb_str_new(ptr, len);
  225.     if (RSTRING(str)->ptr == ptr && RSTRING(str)->len == len)
  226.     return str;
  227.     ret = rb_str_new(ptr, len);
  228.     OBJ_INFECT(ret, str);
  229.     return ret;
  230. }
  231.  
  232. static VALUE
  233. iconv_convert
  234. #ifdef HAVE_PROTOTYPES
  235. (iconv_t cd, VALUE str, int start, int length, struct iconv_env_t* env)
  236. #else /* HAVE_PROTOTYPES */
  237.     (cd, str, start, length, env)
  238.     iconv_t cd;
  239.     VALUE str;
  240.     int start;
  241.     int length;
  242.     struct iconv_env_t *env;
  243. #endif /* HAVE_PROTOTYPES */
  244. {
  245.     VALUE ret = Qfalse;
  246.     VALUE error = Qfalse;
  247.     const char *inptr, *instart;
  248.     size_t inlen;
  249.     /* I believe ONE CHARACTER never exceed this. */
  250.     char buffer[256];
  251.     char *outptr;
  252.     size_t outlen;
  253.  
  254.     if (cd == (iconv_t)-1)
  255.     rb_raise(rb_eArgError, "closed iconv");
  256.  
  257.     if (NIL_P(str)) {
  258. #if BUGGY_ICONV
  259.     /* Reset output pointer or something. */
  260.     inptr = "";
  261.     inlen = 0;
  262.     outptr = buffer;
  263.     outlen = sizeof(buffer);
  264.     error = iconv_try(cd, &inptr, &inlen, &outptr, &outlen);
  265.     if (error)
  266.         iconv_fail(error, Qnil, Qnil, env);
  267. #endif /* BUGGY_ICONV */
  268.     inptr = NULL;
  269.     length = 0;
  270.     } else {
  271.     int slen;
  272.  
  273.     Check_Type(str, T_STRING);
  274.     slen = RSTRING(str)->len;
  275.     inptr = RSTRING(str)->ptr;
  276.  
  277.     if (start < 0 ? (start += slen) < 0 : start >= slen)
  278.         length = 0;
  279.     else if (length < 0 && (length += slen + 1) < 0)
  280.         length = 0;
  281.     else if ((length -= start) < 0)
  282.         length = 0;
  283.     else
  284.         inptr += start;
  285.     }
  286.     instart = inptr;
  287.     inlen = length;
  288.  
  289.     do {
  290.     const char *tmpstart = inptr;
  291.     outptr = buffer;
  292.     outlen = sizeof(buffer);
  293.  
  294.     error = iconv_try(cd, &inptr, &inlen, &outptr, &outlen);
  295.  
  296.     if (0 <= outlen && outlen <= sizeof(buffer)) {
  297.         outlen = sizeof(buffer) - outlen;
  298.         if (outlen > inptr - tmpstart || /* input can't contain output */
  299.         (outlen < inptr - tmpstart && inlen > 0) || /* something skipped */
  300.         memcmp(buffer, tmpstart, outlen)) /* something differs */
  301.         {
  302.         if (NIL_P(str)) {
  303.             ret = rb_str_new(buffer, outlen);
  304.         } else {
  305.             if (ret) {
  306.             ret = rb_str_cat(ret, instart, tmpstart - instart);
  307.             } else {
  308.             ret = rb_str_new(instart, tmpstart - instart);
  309.             OBJ_INFECT(ret, str);
  310.             }
  311.             ret = rb_str_cat(ret, buffer, outlen);
  312.             instart = inptr;
  313.         }
  314.         } else if (!inlen) {
  315.         inptr = tmpstart + outlen;
  316.         }
  317.     } else {
  318.         /* Some iconv() have a bug, return *outlen out of range */
  319.         char errmsg[50];
  320.         sprintf(errmsg, "bug?(output length = %d)", sizeof(buffer) - outlen);
  321.         error = rb_exc_new2(rb_eIconvOutOfRange, errmsg);
  322.     }
  323.  
  324.     if (error) {
  325.         if (!ret)
  326.         ret = rb_str_derive(str, instart, inptr - instart);
  327.         str = rb_str_derive(str, inptr, inlen);
  328.         iconv_fail(error, ret, str, env);
  329.     }
  330.     } while (inlen > 0);
  331.  
  332.     if (!ret)
  333.     ret = rb_str_derive(str, instart, inptr - instart);
  334.     return ret;
  335. }
  336.  
  337.  
  338. /*
  339. =begin
  340. === Class methods
  341. =end
  342. */
  343. /*
  344. =begin
  345. --- Iconv.new(to, from)
  346.     Creates new code converter from a coding-system designated with ((|from|))
  347.     to another one designated with ((|to|)).
  348.     :Parameters
  349.       :((|to|))
  350.         coding-system name for destination.
  351.       :((|from|))
  352.         coding-system name for source.
  353.     :Exceptions
  354.       :(({TypeError}))
  355.         if ((|to|)) or ((|from|)) aren't String
  356.       :(({ArgumentError}))
  357.         if designated converter couldn't find out.
  358.       :(({SystemCallError}))
  359.         when (({iconv_open(3)})) failed.
  360.  
  361. --- Iconv.open(to, from)
  362.     Equivalents to ((<Iconv.new>)) except with in the case of called
  363.     with a block, yields with the new instance and closes it, and
  364.     returns the result which returned from the block.
  365. =end
  366. */
  367. static VALUE
  368. iconv_s_new
  369. #ifdef HAVE_PROTOTYPES
  370. (int argc, VALUE *argv, VALUE klass)
  371. #else /* HAVE_PROTOTYPES */
  372.     (argc, argv, klass)
  373.     int argc;
  374.     VALUE *argv;
  375.     VALUE klass;
  376. #endif /* HAVE_PROTOTYPES */
  377. {
  378.     VALUE obj = Data_Wrap_Struct(klass, 0, ICONV_FREE, 0);
  379.  
  380.     rb_obj_call_init(obj, argc, argv);
  381.  
  382.     return obj;
  383. }
  384.  
  385. static VALUE
  386. iconv_initialize
  387. #ifdef HAVE_PROTOTYPES
  388. (VALUE self, VALUE to, VALUE from)
  389. #else /* HAVE_PROTOTYPES */
  390.     (self, to, from)
  391.     VALUE self;
  392.     VALUE to;
  393.     VALUE from;
  394. #endif /* HAVE_PROTOTYPES */
  395. {
  396.     iconv_free((VALUE)(DATA_PTR(self)));
  397.     DATA_PTR(self) = NULL;
  398.     DATA_PTR(self) = (void *)ICONV2VALUE(iconv_create(to, from));
  399.     return self;
  400. }
  401.  
  402. static VALUE
  403. iconv_s_open
  404. #ifdef HAVE_PROTOTYPES
  405. (VALUE self, VALUE to, VALUE from)
  406. #else /* HAVE_PROTOTYPES */
  407.     (self, to, from)
  408.     VALUE self;
  409.     VALUE to;
  410.     VALUE from;
  411. #endif /* HAVE_PROTOTYPES */
  412. {
  413.     VALUE cd = ICONV2VALUE(iconv_create(to, from));
  414.  
  415.     if (rb_block_given_p()) {
  416.     self = Data_Wrap_Struct(self, NULL, NULL, (void *)cd);
  417.     return rb_ensure(rb_yield, self, (VALUE(*)())iconv_finish, self);
  418.     } else {
  419.     return Data_Wrap_Struct(self, NULL, ICONV_FREE, (void *)cd);
  420.     }
  421. }
  422.  
  423. /*
  424. =begin
  425. --- Iconv.iconv(to, from, *strs)
  426.     Shorthand for
  427.       Iconv.new(to, from) {|cd| (strs + nil).collect {|s| cd.iconv(s)}}
  428.     :Parameters
  429.       :((|to|)), ((|from|))
  430.         see ((<Iconv.new>)).
  431.       :((|strs|))
  432.         strings to be converted.
  433.     :Exceptions
  434.       exceptions thrown by ((<Iconv.new>)) and ((<Iconv#iconv>)).
  435. =end
  436. */
  437.  
  438. static VALUE
  439. iconv_s_convert
  440. #ifdef HAVE_PROTOTYPES
  441. (struct iconv_env_t* env)
  442. #else /* HAVE_PROTOTYPES */
  443.     (env)
  444.     struct iconv_env_t *env;
  445. #endif /* HAVE_PROTOTYPES */
  446. {
  447.     VALUE last = 0;
  448.  
  449.     for (; env->argc > 0; --env->argc, ++env->argv) {
  450.     VALUE s = iconv_convert(env->cd, last = *(env->argv), 0, -1, env);
  451.     rb_funcall3(env->ret, rb_inserter, 1, &s);
  452.     }
  453.  
  454.     if (!NIL_P(last)) {
  455.     VALUE s = iconv_convert(env->cd, Qnil, 0, 0, env);
  456.     if (RSTRING(s)->len)
  457.         rb_funcall3(env->ret, rb_inserter, 1, &s);
  458.     }
  459.  
  460.     return env->ret;
  461. }
  462.  
  463. static VALUE
  464. iconv_s_iconv
  465. #ifdef HAVE_PROTOTYPES
  466. (int argc, VALUE *argv, VALUE self)
  467. #else /* HAVE_PROTOTYPES */
  468.     (argc, argv, self)
  469.     int argc;
  470.     VALUE *argv;
  471.     VALUE self;
  472. #endif /* HAVE_PROTOTYPES */
  473. {
  474.     struct iconv_env_t arg;
  475.  
  476.     if (argc < 2)        /* needs `to' and `from' arguments at least */
  477.     rb_raise(rb_eArgError, "wrong # of arguments (%d for %d)", argc, 2);
  478.  
  479.     arg.argc = argc -= 2;
  480.     arg.argv = argv + 2;
  481.     arg.ret = rb_ary_new2(argc);
  482.     arg.cd = iconv_create(argv[0], argv[1]);
  483.     return rb_ensure(iconv_s_convert, (VALUE)&arg, iconv_free, ICONV2VALUE(arg.cd));
  484. }
  485.  
  486.  
  487. /*
  488. =begin
  489. === Instance methods
  490. =end
  491. */
  492. /*
  493. =begin
  494. --- Iconv#close
  495.     Finishes conversion.
  496.     * After calling this, invoking method ((<Iconv#iconv>)) will cause
  497.       exception, but multiple calls of (({close})) are guaranteed to
  498.       end successfully.
  499.     * Returns a string contains the byte sequence to change the
  500.       output buffer to its initial shift state.
  501. =end
  502. */
  503. static VALUE
  504. iconv_init_state
  505. #ifdef HAVE_PROTOTYPES
  506. (VALUE cd)
  507. #else /* HAVE_PROTOTYPES */
  508.     (cd)
  509.     VALUE cd;
  510. #endif /* HAVE_PROTOTYPES */
  511. {
  512.     return iconv_convert(VALUE2ICONV(cd), Qnil, 0, 0, NULL);
  513. }
  514.  
  515. static VALUE
  516. iconv_finish
  517. #ifdef HAVE_PROTOTYPES
  518. (VALUE self)
  519. #else /* HAVE_PROTOTYPES */
  520.     (self)
  521.     VALUE self;
  522. #endif /* HAVE_PROTOTYPES */
  523. {
  524.     VALUE cd;
  525.  
  526.     Check_Type(self, T_DATA);
  527.  
  528.     cd = (VALUE)DATA_PTR(self);
  529.     if (!cd) return Qnil;
  530.     DATA_PTR(self) = NULL;
  531.  
  532.     return rb_ensure(iconv_init_state, cd, iconv_free, cd);
  533. }
  534.  
  535. /*
  536. =begin
  537. --- Iconv#iconv(str, [ start = 0, [ length = -1 ] ])
  538.     Converts string and returns converted one.
  539.     * In the case of ((|str|)) is (({String})), converts (({str[start, length]})).
  540.       Returns converted string.
  541.     * In the case of ((|str|)) is (({nil})), places ((|converter|))
  542.       itself into initial shift state and just returns a string contains
  543.       the byte sequence to change the output buffer to its initial shift
  544.       state.
  545.     * Otherwise, causes exception.
  546.     :Parameters
  547.       :((|str|))
  548.         string to be converted or (({nil})).
  549.       :((|start|))
  550.         starting offset.
  551.       :((|length|))
  552.         conversion length,
  553.         (({nil})) or (({-1})) means whole string from (({start})).
  554.     :Exceptions
  555.       * ((<Iconv::IllegalSequence>))
  556.       * ((<Iconv::InvalidCharacter>))
  557.       * ((<Iconv::OutOfRange>))
  558. =end
  559. */
  560. static VALUE
  561. iconv_iconv
  562. #ifdef HAVE_PROTOTYPES
  563. (int argc, VALUE *argv, VALUE self)
  564. #else /* HAVE_PROTOTYPES */
  565.     (argc, argv, self)
  566.     int argc;
  567.     VALUE *argv;
  568.     VALUE self;
  569. #endif /* HAVE_PROTOTYPES */
  570. {
  571.     VALUE str, n1, n2;
  572.  
  573.     Check_Type(self, T_DATA);
  574.  
  575.     n1 = n2 = Qnil;
  576.     rb_scan_args(argc, argv, "12", &str, &n1, &n2);
  577.  
  578.     return iconv_convert(VALUE2ICONV(DATA_PTR(self)), str,
  579.              NIL_P(n1) ? 0 : NUM2INT(n1),
  580.              NIL_P(n2) ? -1 : NUM2INT(n1),
  581.              NULL);
  582. }
  583.  
  584.  
  585. /*
  586. =begin
  587. = Exceptions
  588. =end
  589. */
  590. /*
  591. =begin
  592. == Iconv::Failure
  593. Base exceptional attributes from ((<Iconv>)).
  594.  
  595. === Instance methods
  596. =end
  597. */
  598. /*
  599. =begin
  600. --- Iconv::Failure#success
  601.     Returns string(s) translated successfully until the exception occurred.
  602.     * In the case of failure occurred within ((<Iconv.iconv>)), returned
  603.       value is an array of strings translated successfully preceding
  604.       failure and the last element is string on the way.
  605. =end
  606. */
  607. static VALUE
  608. iconv_failure_success
  609. #ifdef HAVE_PROTOTYPES
  610. (VALUE self)
  611. #else /* HAVE_PROTOTYPES */
  612.     (self)
  613.     VALUE self;
  614. #endif /* HAVE_PROTOTYPES */
  615. {
  616.     return rb_ivar_get(self, rb_success);
  617. }
  618.  
  619. /*
  620. =begin
  621. --- Iconv::Failure#failed
  622.     Returns substring of the original string passed to ((<Iconv>)) that
  623.     starts at the character caused the exception. 
  624. =end
  625. */
  626. static VALUE
  627. iconv_failure_failed
  628. #ifdef HAVE_PROTOTYPES
  629. (VALUE self)
  630. #else /* HAVE_PROTOTYPES */
  631.     (self)
  632.     VALUE self;
  633. #endif /* HAVE_PROTOTYPES */
  634. {
  635.     return rb_ivar_get(self, rb_failed);
  636. }
  637.  
  638. /*
  639. =begin
  640. --- Iconv::Failure#inspect
  641.     Returns inspected string like as: #<(({type})): "(({success}))", "(({failed}))">
  642. =end
  643. */
  644. static VALUE
  645. iconv_failure_inspect
  646. #ifdef HAVE_PROTOTYPES
  647. (VALUE self)
  648. #else /* HAVE_PROTOTYPES */
  649.     (self)
  650.     VALUE self;
  651. #endif /* HAVE_PROTOTYPES */
  652. {
  653.     char *cname = rb_class2name(CLASS_OF(self));
  654.     VALUE success = iconv_failure_success(self);
  655.     VALUE failed = iconv_failure_failed(self);
  656.     VALUE str = rb_str_cat(rb_str_new2("#<"), cname, strlen(cname));
  657.     str = rb_str_cat(str, ": ", 2);
  658.     str = rb_str_concat(str, rb_inspect(success));
  659.     str = rb_str_cat(str, ", ", 2);
  660.     str = rb_str_concat(str, rb_inspect(failed));
  661.     return rb_str_cat(str, ">", 1);
  662. }
  663.  
  664. /*
  665.   Hmmm, I don't like to write RD inside of function :-<.
  666.  
  667. =begin
  668. == Iconv::IllegalSequence
  669. Exception in the case of any illegal sequence detected.
  670. === Superclass
  671. (({ArgumentError}))
  672. === Included Modules
  673. ((<Iconv::Failure>))
  674.  
  675. == Iconv::InvalidCharacter
  676. Exception in the case of output coding system can't express the character.
  677. === Superclass
  678. (({ArgumentError}))
  679. === Included Modules
  680. ((<Iconv::Failure>))
  681.  
  682. == Iconv::OutOfRange
  683. Iconv library internal error.  Must not occur.
  684. === Superclass
  685. (({RuntimeError}))
  686. === Included Modules
  687. ((<Iconv::Failure>))
  688. =end
  689. */
  690.  
  691. void
  692. Init_iconv _((void))
  693. {
  694.     VALUE rb_cIconv = rb_define_class("Iconv", rb_cObject);
  695.     rb_define_singleton_method(rb_cIconv, "new", iconv_s_new, -1);
  696.     rb_define_singleton_method(rb_cIconv, "open", iconv_s_open, 2);
  697.     rb_define_singleton_method(rb_cIconv, "iconv", iconv_s_iconv, -1);
  698.     rb_define_method(rb_cIconv, "initialize", iconv_initialize, 2);
  699.     rb_define_method(rb_cIconv, "close", iconv_finish, 0);
  700.     rb_define_method(rb_cIconv, "iconv", iconv_iconv, -1);
  701.     rb_define_const(rb_cIconv, "RCSID", STRING_FREEZE(rb_str_new2(rcsid)));
  702.  
  703.     rb_eIconvFailure = rb_define_module_under(rb_cIconv, "Failure");
  704.     rb_define_method(rb_eIconvFailure, "success", iconv_failure_success, 0);
  705.     rb_define_method(rb_eIconvFailure, "failed", iconv_failure_failed, 0);
  706.     rb_define_method(rb_eIconvFailure, "inspect", iconv_failure_inspect, 0);
  707.  
  708.     rb_eIconvIllegalSeq = rb_define_class_under(rb_cIconv, "IllegalSequence", rb_eArgError);
  709.     rb_eIconvInvalidChar = rb_define_class_under(rb_cIconv, "InvalidCharacter", rb_eArgError);
  710.     rb_eIconvOutOfRange = rb_define_class_under(rb_cIconv, "OutOfRange", rb_eRuntimeError);
  711.     rb_include_module(rb_eIconvIllegalSeq, rb_eIconvFailure);
  712.     rb_include_module(rb_eIconvInvalidChar, rb_eIconvFailure);
  713.     rb_include_module(rb_eIconvOutOfRange, rb_eIconvFailure);
  714.  
  715.     rb_inserter = rb_intern("<<");
  716.     rb_success = rb_intern("success");
  717.     rb_failed = rb_intern("failed");
  718.     rb_mesg = rb_intern("mesg");
  719. }
  720.  
  721.  
  722. /*
  723. =begin
  724. == Example
  725. (1) Instantiate a new ((<Iconv>)), use method ((<Iconv#iconv>)).
  726.       cd = Iconv.new(to, from)
  727.       begin
  728.         input.each {|s| output << cd.iconv(s)}
  729.         output << cd.iconv(nil)      # don't forget this
  730.       ensure
  731.         cd.close
  732.       end
  733. (2) Invoke ((<Iconv.new>)) with a block.
  734.       Iconv.new(to, from) do |cd|
  735.         input.each {|s| output << cd.iconv(s)}
  736.         output << cd.iconv(nil)
  737.       end
  738. (3) Shorthand for (2).
  739.       Iconv.iconv(to, from, *input.to_a)
  740. =end
  741. */
  742.  
  743.  
  744. /*
  745. =begin rlog
  746. = $Log: iconv.c,v $
  747. = Revision 0.4.2.0  2000-09-23 18:03:19+09  nobu
  748. = * defaulted to none-buggy iconv.
  749. =
  750. = Revision 0.4.1.3  2000-08-15 06:46:48+09  nobu
  751. = * declared ((<iconv_fail>)) with (({NORETURN})).
  752. =
  753. = Revision 0.4.1.2  2000-08-14 23:45:59+09  nobu
  754. = * merged with unprotoized version.
  755. =
  756. = Revision 0.4.1.1  2000-08-13 13:17:38+09  nobu
  757. = * ensures out of scope ((<Iconv>)) objects to be closed.
  758. = * raises when closed ((<Iconv>)) passed to ((<Iconv#iconv>)).
  759. = * (({RUBY_DATA_FUNC})) was not a macro.
  760. =
  761. = Revision 0.4.1.0  2000-07-08 07:15:02+09  nobu
  762. = * compatible for 1.4 and 1.5.
  763. =
  764. = Revision 0.4.0.4  2000-07-08 07:15:02+09  nobu
  765. = * defines (({OBJ_INFECT})) macro for 1.4.
  766. =
  767. = Revision 0.4.0.3  2000-07-08 07:03:47+09  nobu
  768. = * uses (({rb_obj_freeze()})) if present.
  769. =
  770. = Revision 0.4.0.2  2000-07-08 06:49:02+09  nobu
  771. = * now calls (({initialize})).
  772. =
  773. = Revision 0.4.0.1  2000-07-07 09:57:59+09  nobu
  774. = * uses (({rb_block_given_p()})).
  775. =
  776. = Revision 0.4  2000-06-11 07:23:24+09  nobu
  777. = * added license notice.
  778. =
  779. = Revision 0.3.3.0  2000-02-26 19:33:35+09  nobu
  780. = Ruby style.
  781. =
  782. = Revision 0.3.2.3  2000-02-21 10:26:12+09  nobu
  783. = Modified rd.
  784. =
  785. = Revision 0.3.2.2  2000-01-01 01:22:59+09  nobu
  786. = * Strict check for change, whether output differs input.
  787. = * Added (({rb_str_derive()})), to ensure infect with tainted object.
  788. =
  789. = Revision 0.3.2.1  1999-12-31 18:21:47+09  nobu
  790. = * Initialize ((|@mesg|)) to failed.inspect and brushed up about
  791. =   exception.
  792. =
  793. = Revision 0.3.2.0  1999-12-15 19:19:15+09  nobu
  794. = * Changed ((<Iconv::Failure>)) initialization.
  795. =
  796. = Revision 0.3.1.1  1999-12-10 14:40:01+09  nobu
  797. = * Workaround for (({iconv()}))'s bug in glibc, by "resetting" with
  798. =   empty string before initializing output shift state.
  799. =
  800. = Revision 0.3.1.0  1999-12-09 19:15:34+09  nobu
  801. = * Added NULL check for ((|outptr|)) before range check for
  802. =   ((|outlen|)).  This may workaround some (({iconv()}))'s bug.
  803. = * Shortened message upon ((<Iconv::OutOfRange>)).
  804. =
  805. = Revision 0.3  1999-12-06 18:51:36+09  nobu
  806. = * Now (({iconv_convert})) no longer pushes returning value into array,
  807. =   except with exception. And uses (({<<})) to add ((|precedents|)),
  808. =   in other words, it's no longer bound to Array.
  809. = * (({iconv_each})) also uses (({<<})).
  810. = * ((<Iconv.iconv>)) no longer append surplus empty string.
  811. =
  812. = Revision 0.2.1.0  1999-12-06 16:33:53+09  nobu
  813. = * Bug-fix of the workaround while converting UCS-4 string.
  814. =
  815. = Revision 0.2  1999-12-02 17:03:29+09  nobu
  816. = * Workaround for (({iconv()}))'s bug returns horrible value as
  817. =   ((|outbytesleft|)).
  818. = * Now ((<Iconv::Failure>)) is a module. So, the exceptions include it.
  819. = * ((<Iconv::Failre#success>)) had been (({nil})).
  820. = * (({iconv_convert()})) had returned original string.
  821. =
  822. = Revision 0.1  1999-12-01 20:28:09+09  nobu
  823. = Release version
  824. =
  825. = Revision 0.0.2.0  1999-11-29 21:17:52+09  nobu
  826. = * Changed Iconv#iconv's arguments order.
  827. = * Now returns translation failure with exception.
  828. =
  829. = Revision 0.0.1.0  1999-11-21 12:27:48+09  nobu
  830. = * Workaround for buggy iconv
  831. = * Obsoleted iterator Iconv.iconv
  832. = * Type check for String
  833. = * Some bug-fix
  834. =
  835. = Revision 0.0.0.3  1999-11-18 16:24:11+09  nobu
  836. = * Signature of iconv_s_iconv() had changed.
  837. =
  838. = Revision 0.0.0.2  1999-11-18 16:12:51+09  nobu
  839. = * Now iconv_convert() accepts NULL for inlen.
  840. = * Now Iconv.iconv can be called as iterator.
  841. =
  842. = Revision 0.0.0.1  1999-11-18 10:03:42+09  nobu
  843. = * Taint new string when original one is tainted.
  844. = * Added RCSID.
  845. =
  846. = Revision 0.0  1999-11-17 18:32:02+09  nobu
  847. =end
  848. */
  849.