ext/strscan/strscan.c


DEFINITIONS

This source file includes following functions.
  1. rb_obj_freeze
  2. infect
  3. extract_range
  4. extract_beg_len
  5. strscan_mark
  6. strscan_free
  7. strscan_s_allocate
  8. strscan_initialize
  9. strscan_s_mustc
  10. strscan_reset
  11. strscan_terminate
  12. strscan_get_string
  13. strscan_set_string
  14. strscan_get_pos
  15. strscan_set_pos
  16. strscan_do_scan
  17. strscan_scan
  18. strscan_match_p
  19. strscan_skip
  20. strscan_check
  21. strscan_scan_full
  22. strscan_scan_until
  23. strscan_exist_p
  24. strscan_skip_until
  25. strscan_check_until
  26. strscan_search_full
  27. adjust_registers_to_matched
  28. strscan_getch
  29. strscan_get_byte
  30. strscan_peek
  31. strscan_unscan
  32. strscan_eos_p
  33. strscan_rest_p
  34. strscan_matched_p
  35. strscan_matched
  36. strscan_matched_size
  37. strscan_aref
  38. strscan_pre_match
  39. strscan_post_match
  40. strscan_rest
  41. strscan_rest_size
  42. strscan_inspect
  43. inspect_before
  44. inspect_after
  45. Init_strscan


   1  /* vi:set sw=4:
   2  
   3      strscan.c
   4  
   5      Copyright (c) 1999-2002 Minero Aoki <aamine@loveruby.net>
   6  
   7      This program is free software.
   8      You can distribute/modify this program under the terms of
   9      the Ruby License. For details, see the file COPYING.
  10  
  11      $Id: strscan.c,v 1.4 2002/08/02 00:10:19 aamine Exp $
  12  
  13  */
  14  
  15  
  16  #include "ruby.h"
  17  #include "re.h"
  18  #include "version.h"
  19  
  20  #if (RUBY_VERSION_CODE < 150)
  21  #  define rb_eRangeError rb_eArgError
  22  #  define rb_obj_freeze(obj) rb_str_freeze(obj)
  23  #endif
  24  
  25  #define STRSCAN_VERSION "0.7.0"
  26  
  27  /* =======================================================================
  28                           Data Type Definitions
  29     ======================================================================= */
  30  
  31  static VALUE StringScanner;
  32  static VALUE ScanError;
  33  
  34  struct strscanner
  35  {
  36      /* multi-purpose flags */
  37      unsigned long flags;
  38  #define FLAG_MATCHED (1 << 0)
  39  
  40      /* the string to scan */
  41      VALUE str;
  42      
  43      /* scan pointers */
  44      long prev;   /* legal only when MATCHED_P(s) */
  45      long curr;   /* always legal */
  46  
  47      /* the regexp register; legal only when MATCHED_P(s) */
  48      struct re_registers regs;
  49  };
  50  
  51  #define MATCHED_P(s)          ((s)->flags & FLAG_MATCHED)
  52  #define MATCHED(s)             (s)->flags |= FLAG_MATCHED
  53  #define CLEAR_MATCH_STATUS(s)  (s)->flags &= ~FLAG_MATCHED
  54  
  55  #define S_PTR(s)  (RSTRING((s)->str)->ptr)
  56  #define S_LEN(s)  (RSTRING((s)->str)->len)
  57  #define S_END(s)  (S_PTR(s) + S_LEN(s))
  58  #define CURPTR(s) (S_PTR(s) + (s)->curr)
  59  #define S_RESTLEN(s) (S_LEN(s) - (s)->curr)
  60  
  61  #define EOS_P(s) ((s)->curr >= RSTRING(p->str)->len)
  62  
  63  #define GET_SCANNER(obj,var) do {\
  64      Data_Get_Struct(obj, struct strscanner, var);\
  65      if (NIL_P(var->str)) rb_raise(rb_eArgError, "uninitialized StringScanner object");\
  66  } while (0)
  67  
  68  /* =======================================================================
  69                              Function Prototypes
  70     ======================================================================= */
  71  
  72  static VALUE infect _((VALUE str, struct strscanner *p));
  73  static VALUE extract_range _((struct strscanner *p, long beg_i, long end_i));
  74  static VALUE extract_beg_len _((struct strscanner *p, long beg_i, long len));
  75  
  76  static void strscan_mark _((struct strscanner *p));
  77  static void strscan_free _((struct strscanner *p));
  78  static VALUE strscan_s_allocate _((VALUE klass));
  79  static VALUE strscan_initialize _((int argc, VALUE *argv, VALUE self));
  80  
  81  static VALUE strscan_s_mustc _((VALUE self));
  82  static VALUE strscan_terminate _((VALUE self));
  83  static VALUE strscan_get_string _((VALUE self));
  84  static VALUE strscan_set_string _((VALUE self, VALUE str));
  85  static VALUE strscan_get_pos _((VALUE self));
  86  static VALUE strscan_set_pos _((VALUE self, VALUE pos));
  87  static VALUE strscan_do_scan _((VALUE self, VALUE regex,
  88                                  int succptr, int getstr, int headonly));
  89  static VALUE strscan_scan _((VALUE self, VALUE re));
  90  static VALUE strscan_match_p _((VALUE self, VALUE re));
  91  static VALUE strscan_skip _((VALUE self, VALUE re));
  92  static VALUE strscan_check _((VALUE self, VALUE re));
  93  static VALUE strscan_scan_full _((VALUE self, VALUE re,
  94                                    VALUE succp, VALUE getp));
  95  static VALUE strscan_scan_until _((VALUE self, VALUE re));
  96  static VALUE strscan_skip_until _((VALUE self, VALUE re));
  97  static VALUE strscan_check_until _((VALUE self, VALUE re));
  98  static VALUE strscan_search_full _((VALUE self, VALUE re,
  99                                      VALUE succp, VALUE getp));
 100  static void adjust_registers_to_matched _((struct strscanner *p));
 101  static VALUE strscan_getch _((VALUE self));
 102  static VALUE strscan_get_byte _((VALUE self));
 103  static VALUE strscan_peek _((VALUE self, VALUE len));
 104  static VALUE strscan_unscan _((VALUE self));
 105  static VALUE strscan_eos_p _((VALUE self));
 106  static VALUE strscan_rest_p _((VALUE self));
 107  static VALUE strscan_matched_p _((VALUE self));
 108  static VALUE strscan_matched _((VALUE self));
 109  static VALUE strscan_matched_size _((VALUE self));
 110  static VALUE strscan_aref _((VALUE self, VALUE idx));
 111  static VALUE strscan_pre_match _((VALUE self));
 112  static VALUE strscan_post_match _((VALUE self));
 113  static VALUE strscan_rest _((VALUE self));
 114  static VALUE strscan_rest_size _((VALUE self));
 115  
 116  static VALUE strscan_inspect _((VALUE self));
 117  static char* inspect_before _((struct strscanner *p, char *buf));
 118  static char* inspect_after _((struct strscanner *p, char *buf));
 119  
 120  /* =======================================================================
 121                                     Utils
 122     ======================================================================= */
 123  
 124  static VALUE
 125  infect(str, p)
 126      VALUE str;
 127      struct strscanner *p;
 128  {
 129      OBJ_INFECT(str, p->str);
 130      return str;
 131  }
 132  
 133  static VALUE
 134  extract_range(p, beg_i, end_i)
 135      struct strscanner *p;
 136      long beg_i, end_i;
 137  {
 138      return infect(rb_str_new(S_PTR(p) + beg_i, end_i - beg_i), p);
 139  }
 140  
 141  static VALUE
 142  extract_beg_len(p, beg_i, len)
 143      struct strscanner *p;
 144      long beg_i, len;
 145  {
 146      return infect(rb_str_new(S_PTR(p) + beg_i, len), p);
 147  }
 148  
 149  
 150  /* =======================================================================
 151                                 Constructor
 152     ======================================================================= */
 153  
 154  
 155  static void
 156  strscan_mark(p)
 157      struct strscanner *p;
 158  {
 159      rb_gc_mark(p->str);
 160  }
 161  
 162  static void
 163  strscan_free(p)
 164      struct strscanner *p;
 165  {
 166      re_free_registers(&(p->regs));
 167      memset(p, sizeof(struct strscanner), 0);
 168      free(p);
 169  }
 170  
 171  static VALUE
 172  strscan_s_allocate(klass)
 173      VALUE klass;
 174  {
 175      struct strscanner *p;
 176      
 177      p = ALLOC(struct strscanner);
 178      MEMZERO(p, struct strscanner, 1);
 179      CLEAR_MATCH_STATUS(p);
 180      MEMZERO(&(p->regs), struct re_registers, 1);
 181      p->str = Qnil;
 182      return Data_Wrap_Struct(klass, strscan_mark, strscan_free, p);
 183  }
 184  
 185  static VALUE
 186  strscan_initialize(argc, argv, self)
 187      int argc;
 188      VALUE *argv;
 189      VALUE self;
 190  {
 191      struct strscanner *p;
 192      VALUE str, need_dup;
 193  
 194      Data_Get_Struct(self, struct strscanner, p);
 195      if (rb_scan_args(argc, argv, "11", &str, &need_dup) == 1)
 196          need_dup = Qtrue;
 197      StringValue(str);
 198      p->str = RTEST(need_dup) ? rb_str_dup(str) : str;
 199      rb_obj_freeze(p->str);
 200  
 201      return self;
 202  }
 203  
 204  
 205  /* =======================================================================
 206                            Instance Methods
 207     ======================================================================= */
 208  
 209  static VALUE
 210  strscan_s_mustc(self)
 211      VALUE self;
 212  {
 213      return self;
 214  }
 215  
 216  static VALUE
 217  strscan_reset(self)
 218      VALUE self;
 219  {
 220      struct strscanner *p;
 221  
 222      GET_SCANNER(self, p);
 223      p->curr = 0;
 224      CLEAR_MATCH_STATUS(p);
 225      return self;
 226  }
 227  
 228  static VALUE
 229  strscan_terminate(self)
 230      VALUE self;
 231  {
 232      struct strscanner *p;
 233  
 234      GET_SCANNER(self, p);
 235      p->curr = S_LEN(p);
 236      CLEAR_MATCH_STATUS(p);
 237      return self;
 238  }
 239  
 240  static VALUE
 241  strscan_get_string(self)
 242      VALUE self;
 243  {
 244      struct strscanner *p;
 245  
 246      GET_SCANNER(self, p);
 247      return p->str;
 248  }
 249  
 250  static VALUE
 251  strscan_set_string(self, str)
 252      VALUE self, str;
 253  {
 254      struct strscanner *p;
 255  
 256      Data_Get_Struct(self, struct strscanner, p);
 257      StringValue(str);
 258      p->str = rb_str_dup(str);
 259      rb_obj_freeze(p->str);
 260      p->curr = 0;
 261      CLEAR_MATCH_STATUS(p);
 262      return str;
 263  }
 264  
 265  static VALUE
 266  strscan_get_pos(self)
 267      VALUE self;
 268  {
 269      struct strscanner *p;
 270  
 271      GET_SCANNER(self, p);
 272      return INT2FIX(p->curr);
 273  }
 274  
 275  static VALUE
 276  strscan_set_pos(self, v)
 277      VALUE self, v;
 278  {
 279      struct strscanner *p;
 280      long i;
 281  
 282      GET_SCANNER(self, p);
 283      i = NUM2INT(v);
 284      if (i < 0) i += S_LEN(p);
 285      if (i < 0) rb_raise(rb_eRangeError, "index out of range");
 286      if (i > S_LEN(p)) rb_raise(rb_eRangeError, "index out of range");
 287      p->curr = i;
 288      return INT2NUM(i);
 289  }
 290  
 291  
 292  /* I should implement this function? */
 293  #define strscan_prepare_re(re)  /* none */
 294  
 295  static VALUE
 296  strscan_do_scan(self, regex, succptr, getstr, headonly)
 297      VALUE self, regex;
 298      int succptr, getstr, headonly;
 299  {
 300      struct strscanner *p;
 301      int ret;
 302  
 303      Check_Type(regex, T_REGEXP);
 304      GET_SCANNER(self, p);
 305  
 306      CLEAR_MATCH_STATUS(p);
 307      strscan_prepare_re(regex);
 308      if (headonly) {
 309          ret = re_match(RREGEXP(regex)->ptr,
 310                         CURPTR(p), S_RESTLEN(p),
 311                         0,
 312                         &(p->regs));
 313      }
 314      else {
 315          ret = re_search(RREGEXP(regex)->ptr,
 316                          CURPTR(p), S_RESTLEN(p),
 317                          0,
 318                          S_RESTLEN(p),
 319                          &(p->regs));
 320      }
 321  
 322      if (ret == -2) rb_raise(ScanError, "regexp buffer overflow");
 323      if (ret < 0) {
 324          /* not matched */
 325          return Qnil;
 326      }
 327  
 328      MATCHED(p);
 329      p->prev = p->curr;
 330      if (succptr) {
 331          p->curr += p->regs.end[0];
 332      }
 333      if (getstr) {
 334          return extract_beg_len(p, p->prev, p->regs.end[0]);
 335      }
 336      else {
 337          return INT2FIX(p->regs.end[0]);
 338      }
 339  }
 340  
 341  static VALUE
 342  strscan_scan(self, re)
 343      VALUE self, re;
 344  {
 345      return strscan_do_scan(self, re, 1, 1, 1);
 346  }
 347  
 348  static VALUE
 349  strscan_match_p(self, re)
 350      VALUE self, re;
 351  {
 352      return strscan_do_scan(self, re, 0, 0, 1);
 353  }
 354  
 355  static VALUE
 356  strscan_skip(self, re)
 357      VALUE self, re;
 358  {
 359      return strscan_do_scan(self, re, 1, 0, 1);
 360  }
 361  
 362  static VALUE
 363  strscan_check(self, re)
 364      VALUE self, re;
 365  {
 366      return strscan_do_scan(self, re, 0, 1, 1);
 367  }
 368  
 369  static VALUE
 370  strscan_scan_full(self, re, s, f)
 371      VALUE self, re, s, f;
 372  {
 373      return strscan_do_scan(self, re, RTEST(s), RTEST(f), 1);
 374  }
 375  
 376  
 377  static VALUE
 378  strscan_scan_until(self, re)
 379      VALUE self, re;
 380  {
 381      return strscan_do_scan(self, re, 1, 1, 0);
 382  }
 383  
 384  static VALUE
 385  strscan_exist_p(self, re)
 386      VALUE self, re;
 387  {
 388      return strscan_do_scan(self, re, 0, 0, 0);
 389  }
 390  
 391  static VALUE
 392  strscan_skip_until(self, re)
 393      VALUE self, re;
 394  {
 395      return strscan_do_scan(self, re, 1, 0, 0);
 396  }
 397  
 398  static VALUE
 399  strscan_check_until(self, re)
 400      VALUE self, re;
 401  {
 402      return strscan_do_scan(self, re, 0, 1, 0);
 403  }
 404  
 405  static VALUE
 406  strscan_search_full(self, re, s, f)
 407      VALUE self, re, s, f;
 408  {
 409      return strscan_do_scan(self, re, RTEST(s), RTEST(f), 0);
 410  }
 411  
 412  /* DANGEROUS; need to synchronize with regex.c */
 413  static void
 414  adjust_registers_to_matched(p)
 415      struct strscanner *p;
 416  {
 417      if (p->regs.allocated == 0) {
 418          p->regs.beg = ALLOC_N(int, RE_NREGS);
 419          p->regs.end = ALLOC_N(int, RE_NREGS);
 420          p->regs.allocated = RE_NREGS;
 421      }
 422      p->regs.num_regs = 1;
 423      p->regs.beg[0] = 0;
 424      p->regs.end[0] = p->curr - p->prev;
 425  }
 426  
 427  static VALUE
 428  strscan_getch(self)
 429      VALUE self;
 430  {
 431      struct strscanner *p;
 432      long len;
 433  
 434      GET_SCANNER(self, p);
 435      CLEAR_MATCH_STATUS(p);
 436      if (EOS_P(p))
 437          return Qnil;
 438  
 439      len = mbclen(*CURPTR(p));
 440      if (p->curr + len > S_LEN(p))
 441          len = S_LEN(p) - p->curr;
 442      p->prev = p->curr;
 443      p->curr += len;
 444      MATCHED(p);
 445      adjust_registers_to_matched(p);
 446      return extract_range(p, p->prev + p->regs.beg[0],
 447                              p->prev + p->regs.end[0]);
 448  }
 449  
 450  static VALUE
 451  strscan_get_byte(self)
 452      VALUE self;
 453  {
 454      struct strscanner *p;
 455  
 456      GET_SCANNER(self, p);
 457      CLEAR_MATCH_STATUS(p);
 458      if (EOS_P(p))
 459          return Qnil;
 460  
 461      p->prev = p->curr;
 462      p->curr++;
 463      MATCHED(p);
 464      adjust_registers_to_matched(p);
 465      return extract_range(p, p->prev + p->regs.beg[0],
 466                              p->prev + p->regs.end[0]);
 467  }
 468  
 469  
 470  static VALUE
 471  strscan_peek(self, vlen)
 472      VALUE self, vlen;
 473  {
 474      struct strscanner *p;
 475      long len;
 476  
 477      GET_SCANNER(self, p);
 478  
 479      len = NUM2LONG(vlen);
 480      if (EOS_P(p))
 481          return infect(rb_str_new("", 0), p);
 482  
 483      if (p->curr + len > S_LEN(p))
 484          len = S_LEN(p) - p->curr;
 485      return extract_beg_len(p, p->curr, len);
 486  }
 487  
 488  
 489  static VALUE
 490  strscan_unscan(self)
 491      VALUE self;
 492  {
 493      struct strscanner *p;
 494  
 495      GET_SCANNER(self, p);
 496      if (! MATCHED_P(p))
 497          rb_raise(ScanError, "cannot unscan: prev match had failed");
 498  
 499      p->curr = p->prev;
 500      CLEAR_MATCH_STATUS(p);
 501      return self;
 502  }
 503  
 504  
 505  static VALUE
 506  strscan_eos_p(self)
 507      VALUE self;
 508  {
 509      struct strscanner *p;
 510  
 511      GET_SCANNER(self, p);
 512      if (EOS_P(p))
 513          return Qtrue;
 514      else
 515          return Qfalse;
 516  }
 517  
 518  static VALUE
 519  strscan_rest_p(self)
 520      VALUE self;
 521  {
 522      struct strscanner *p;
 523  
 524      GET_SCANNER(self, p);
 525      if (EOS_P(p))
 526          return Qfalse;
 527      else
 528          return Qtrue;
 529  }
 530  
 531  
 532  static VALUE
 533  strscan_matched_p(self)
 534      VALUE self;
 535  {
 536      struct strscanner *p;
 537  
 538      GET_SCANNER(self, p);
 539      if (MATCHED_P(p))
 540          return Qtrue;
 541      else
 542          return Qfalse;
 543  }
 544  
 545  static VALUE
 546  strscan_matched(self)
 547      VALUE self;
 548  {
 549      struct strscanner *p;
 550  
 551      GET_SCANNER(self, p);
 552      if (! MATCHED_P(p)) return Qnil;
 553  
 554      return extract_range(p, p->prev + p->regs.beg[0],
 555                              p->prev + p->regs.end[0]);
 556  }
 557  
 558  static VALUE
 559  strscan_matched_size(self)
 560      VALUE self;
 561  {
 562      struct strscanner *p;
 563  
 564      GET_SCANNER(self, p);
 565      if (! MATCHED_P(p)) return Qnil;
 566  
 567      return INT2NUM(p->regs.end[0] - p->regs.beg[0]);
 568  }
 569  
 570  static VALUE
 571  strscan_aref(self, idx)
 572      VALUE self, idx;
 573  {
 574      struct strscanner *p;
 575      long i;
 576  
 577      GET_SCANNER(self, p);
 578      if (! MATCHED_P(p))        return Qnil;
 579      
 580      i = NUM2LONG(idx);
 581      if (i < 0)
 582          i += p->regs.num_regs;
 583      if (i < 0)                 return Qnil;
 584      if (i >= p->regs.num_regs) return Qnil;
 585      if (p->regs.beg[i] == -1)  return Qnil;
 586  
 587      return extract_range(p, p->prev + p->regs.beg[i],
 588                              p->prev + p->regs.end[i]);
 589  }
 590  
 591  static VALUE
 592  strscan_pre_match(self)
 593      VALUE self;
 594  {
 595      struct strscanner *p;
 596  
 597      GET_SCANNER(self, p);
 598      if (! MATCHED_P(p)) return Qnil;
 599  
 600      return extract_range(p, 0, p->prev + p->regs.beg[0]);
 601  }
 602  
 603  static VALUE
 604  strscan_post_match(self)
 605      VALUE self;
 606  {
 607      struct strscanner *p;
 608  
 609      GET_SCANNER(self, p);
 610      if (! MATCHED_P(p)) return Qnil;
 611  
 612      return extract_range(p, p->prev + p->regs.end[0], S_LEN(p));
 613  }
 614  
 615  
 616  static VALUE
 617  strscan_rest(self)
 618      VALUE self;
 619  {
 620      struct strscanner *p;
 621  
 622      GET_SCANNER(self, p);
 623      if (EOS_P(p)) {
 624          return infect(rb_str_new("", 0), p);
 625      }
 626      return extract_range(p, p->curr, S_LEN(p));
 627  }
 628  
 629  static VALUE
 630  strscan_rest_size(self)
 631      VALUE self;
 632  {
 633      struct strscanner *p;
 634      long i;
 635  
 636      GET_SCANNER(self, p);
 637      if (EOS_P(p)) {
 638          return INT2FIX(0);
 639      }
 640  
 641      i = S_LEN(p) - p->curr;
 642      return INT2FIX(i);
 643  }
 644  
 645  
 646  #define INSPECT_LENGTH 5
 647  
 648  static VALUE
 649  strscan_inspect(self)
 650      VALUE self;
 651  {
 652      struct strscanner *p;
 653      char buf[256];
 654      char buf_before[16];
 655      char buf_after[16];
 656      long len;
 657  
 658      Data_Get_Struct(self, struct strscanner, p);
 659      if (NIL_P(p->str)) {
 660          len = sprintf(buf, "#<%s (uninitialized)>",
 661                        rb_class2name(CLASS_OF(self)));
 662          return rb_str_new(buf, len);
 663      }
 664      if (EOS_P(p)) {
 665          len = sprintf(buf, "#<%s fin>",
 666                        rb_class2name(CLASS_OF(self)));
 667          return rb_str_new(buf, len);
 668      }
 669      len = sprintf(buf, "#<%s %ld/%ld %s@%s>",
 670                    rb_class2name(CLASS_OF(self)),
 671                    p->curr, S_LEN(p),
 672                    inspect_before(p, buf_before),
 673                    inspect_after(p, buf_after));
 674      return rb_str_new(buf, len);
 675  }
 676  
 677  static char*
 678  inspect_before(p, buf)
 679      struct strscanner *p;
 680      char *buf;
 681  {
 682      char *bp = buf;
 683      long len;
 684  
 685      if (p->curr == 0) return "";
 686      *bp++ = '"';
 687      if (p->curr > INSPECT_LENGTH) {
 688          strcpy(bp, "..."); bp += 3;
 689          len = INSPECT_LENGTH;
 690      }
 691      else {
 692          len = p->curr;
 693      }
 694      memcpy(bp, CURPTR(p) - len, len); bp += len;
 695      *bp++ = '"';
 696      *bp++ = ' ';
 697      *bp++ = '\0';
 698      return buf;
 699  }
 700  
 701  static char*
 702  inspect_after(p, buf)
 703      struct strscanner *p;
 704      char *buf;
 705  {
 706      char *bp = buf;
 707      long len;
 708  
 709      *bp++ = ' ';
 710      *bp++ = '"';
 711      len = S_LEN(p) - p->curr;
 712      if (len > INSPECT_LENGTH) {
 713          len = INSPECT_LENGTH;
 714          memcpy(bp, CURPTR(p), len); bp += len;
 715          strcpy(bp, "..."); bp += 3;
 716      }
 717      else {
 718          memcpy(bp, CURPTR(p), len); bp += len;
 719      }
 720      *bp++ = '"';
 721      *bp++ = '\0';
 722      return buf;
 723  }
 724  
 725  /* =======================================================================
 726                                Ruby Interface
 727     ======================================================================= */
 728  
 729  void
 730  Init_strscan()
 731  {
 732      ID id_scanerr = rb_intern("ScanError");
 733      volatile VALUE tmp;
 734  
 735      if (rb_const_defined(rb_cObject, id_scanerr)) {
 736          ScanError = rb_const_get(rb_cObject, id_scanerr);
 737      }
 738      else {
 739          ScanError = rb_define_class_id(id_scanerr, rb_eStandardError);
 740      }
 741  
 742      StringScanner = rb_define_class("StringScanner", rb_cObject);
 743      tmp = rb_str_new2(STRSCAN_VERSION);
 744      rb_obj_freeze(tmp);
 745      rb_const_set(StringScanner, rb_intern("Version"), tmp);
 746      tmp = rb_str_new2("$Id: strscan.c,v 1.4 2002/08/02 00:10:19 aamine Exp $");
 747      rb_obj_freeze(tmp);
 748      rb_const_set(StringScanner, rb_intern("Id"), tmp);
 749      
 750      rb_define_singleton_method(StringScanner, "allocate",
 751                                 strscan_s_allocate, 0);
 752      rb_define_private_method(StringScanner, "initialize",
 753                               strscan_initialize, -1);
 754      rb_define_singleton_method(StringScanner, "must_C_version",
 755                                 strscan_s_mustc, 0);
 756      rb_define_method(StringScanner, "reset",       strscan_reset,       0);
 757      rb_define_method(StringScanner, "terminate",   strscan_terminate,   0);
 758      rb_define_method(StringScanner, "clear",       strscan_terminate,   0);
 759      rb_define_method(StringScanner, "string",      strscan_get_string,  0);
 760      rb_define_method(StringScanner, "string=",     strscan_set_string,  1);
 761      rb_define_method(StringScanner, "pos",         strscan_get_pos,     0);
 762      rb_define_method(StringScanner, "pos=",        strscan_set_pos,     1);
 763      rb_define_method(StringScanner, "pointer",     strscan_get_pos,     0);
 764      rb_define_method(StringScanner, "pointer=",    strscan_set_pos,     1);
 765  
 766      rb_define_method(StringScanner, "scan",        strscan_scan,        1);
 767      rb_define_method(StringScanner, "skip",        strscan_skip,        1);
 768      rb_define_method(StringScanner, "match?",      strscan_match_p,     1);
 769      rb_define_method(StringScanner, "check",       strscan_check,       1);
 770      rb_define_method(StringScanner, "scan_full",   strscan_scan_full,   3);
 771  
 772      rb_define_method(StringScanner, "scan_until",  strscan_scan_until,  1);
 773      rb_define_method(StringScanner, "skip_until",  strscan_skip_until,  1);
 774      rb_define_method(StringScanner, "exist?",      strscan_exist_p,     1);
 775      rb_define_method(StringScanner, "check_until", strscan_check_until, 1);
 776      rb_define_method(StringScanner, "search_full", strscan_search_full, 3);
 777  
 778      rb_define_method(StringScanner, "getch",       strscan_getch,       0);
 779      rb_define_method(StringScanner, "get_byte",    strscan_get_byte,    0);
 780      rb_define_method(StringScanner, "getbyte",     strscan_get_byte,    0);
 781      rb_define_method(StringScanner, "peek",        strscan_peek,        1);
 782      rb_define_method(StringScanner, "peep",        strscan_peek,        1);
 783  
 784      rb_define_method(StringScanner, "unscan",      strscan_unscan,      0);
 785  
 786      rb_define_method(StringScanner, "eos?",        strscan_eos_p,       0);
 787      rb_define_method(StringScanner, "empty?",      strscan_eos_p,       0);
 788      rb_define_method(StringScanner, "rest?",       strscan_rest_p,      0);
 789  
 790      rb_define_method(StringScanner, "matched?",    strscan_matched_p,   0);
 791      rb_define_method(StringScanner, "matched",     strscan_matched,     0);
 792      rb_define_method(StringScanner, "matched_size", strscan_matched_size, 0);
 793      rb_define_method(StringScanner, "matchedsize", strscan_matched_size, 0);
 794      rb_define_method(StringScanner, "[]",          strscan_aref,        1);
 795      rb_define_method(StringScanner, "pre_match",   strscan_pre_match,   0);
 796      rb_define_method(StringScanner, "post_match",  strscan_post_match,  0);
 797  
 798      rb_define_method(StringScanner, "rest",        strscan_rest,        0);
 799      rb_define_method(StringScanner, "rest_size",   strscan_rest_size,   0);
 800      rb_define_method(StringScanner, "restsize",    strscan_rest_size,   0);
 801  
 802      rb_define_method(StringScanner, "inspect",     strscan_inspect,     0);
 803  }