1 /*
2 Copyright (C) 2007-2017,2018 John E. Davis
3 
4 This file is part of the S-Lang Library.
5 
6 The S-Lang Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
10 
11 The S-Lang Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with this library; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19 USA.
20 */
21 
22 #include "config.h"
23 #include <stdio.h>
24 #include <slang.h>
25 #include <string.h>
26 
27 #include <oniguruma.h>
28 
29 SLANG_MODULE(onig);
30 
31 #if 0
32 /* This function converts a slang RE to a pcre expression.  It performs the
33  * following transformations:
34  *    (     -->   \(
35  *    )     -->   \)
36  *    #     -->   \#
37  *    |     -->   \|
38  *    {     -->   \{
39  *    }     -->   \}
40  *   \<     -->   \b
41  *   \>     -->   \b
42  *   \C     -->   (?i)
43  *   \c     -->   (?-i)
44  *   \(     -->   (
45  *   \)     -->   )
46  *   \{     -->   {
47  *   \}     -->   }
48  * Anything else?
49  */
50 static char *_slang_to_pcre (char *slpattern)
51 {
52    char *pattern, *p, *s;
53    unsigned int len;
54    int in_bracket;
55    char ch;
56 
57    len = strlen (slpattern);
58    pattern = SLmalloc (3*len + 1);
59    if (pattern == NULL)
60      return NULL;
61 
62    p = pattern;
63    s = slpattern;
64    in_bracket = 0;
65    while ((ch = *s++) != 0)
66      {
67 	switch (ch)
68 	  {
69 	   case '{':
70 	   case '}':
71 	   case '(':
72 	   case ')':
73 	   case '#':
74 	   case '|':
75 	     if (0 == in_bracket) *p++ = '\\';
76 	     *p++ = ch;
77 	     break;
78 
79 	   case '[':
80 	     in_bracket = 1;
81 	     *p++ = ch;
82 	     break;
83 
84 	   case ']':
85 	     in_bracket = 0;
86 	     *p++ = ch;
87 	     break;
88 
89 	   case '\\':
90 	     ch = *s++;
91 	     switch (ch)
92 	       {
93 		case 0:
94 		  s--;
95 		  break;
96 
97 		case '<':
98 		case '>':
99 		  *p++ = '\\'; *p++ = 'b';
100 		  break;
101 
102 		case '(':
103 		case ')':
104 		case '{':
105 		case '}':
106 		  *p++ = ch;
107 		  break;
108 
109 		case 'C':
110 		  *p++ = '('; *p++ = '?'; *p++ = 'i'; *p++ = ')';
111 		  break;
112 		case 'c':
113 		  *p++ = '('; *p++ = '?'; *p++ = '-'; *p++ = 'i'; *p++ = ')';
114 		  break;
115 
116 		default:
117 		  *p++ = '\\';
118 		  *p++ = ch;
119 	       }
120 	     break;
121 
122 	   default:
123 	     *p++ = ch;
124 	     break;
125 	  }
126      }
127    *p = 0;
128 
129    s = SLang_create_slstring (pattern);
130    SLfree (pattern);
131    return s;
132 }
133 
134 static void slang_to_pcre (char *pattern)
135 {
136    /* NULL ok in code below */
137    pattern = _slang_to_pcre (pattern);
138    (void) SLang_push_string (pattern);
139    SLang_free_slstring (pattern);
140 }
141 #endif
142 
143 static int slOnig_Error = -1;
144 static int Onig_Type_Id = 0;
145 
throw_onig_error(int err_code,OnigErrorInfo * einfo)146 static void throw_onig_error (int err_code, OnigErrorInfo *einfo)
147 {
148    UChar err_buf[ONIG_MAX_ERROR_MESSAGE_LEN];
149 
150    (void) onig_error_code_to_str (err_buf, err_code, einfo);
151    SLang_verror (slOnig_Error, "%s", err_buf);
152 }
153 
154 /* These 3 typedefs should be merged into a union, but C does not support
155  * initializing a union.
156  */
157 typedef struct
158 {
159    SLFUTURE_CONST char *name;
160    /* VOID_STAR ptr; */
161    void *ptr;
162 }
163 Name_Map_Type;
164 
165 typedef struct
166 {
167    SLFUTURE_CONST char *name;
168    OnigSyntaxType *syn;
169 }
170 Syntax_Table_Map_Type;
171 
172 typedef struct
173 {
174    SLFUTURE_CONST char *name;
175    OnigEncodingType *encoding;
176 }
177 Encoding_Table_Map_Type;
178 
pop_onig_name_ptr(Name_Map_Type * map,SLFUTURE_CONST char * onig_object)179 static VOID_STAR pop_onig_name_ptr (Name_Map_Type *map, SLFUTURE_CONST char *onig_object)
180 {
181    char *str;
182 
183    if (-1 == SLang_pop_slstring (&str))
184      return NULL;
185 
186    while (map->name != NULL)
187      {
188 	if (0 == strcmp (str, map->name))
189 	  {
190 	     SLang_free_slstring (str);
191 	     return map->ptr;
192 	  }
193 	map++;
194      }
195 
196    SLang_verror (SL_InvalidParm_Error, "Unsupported or unknown onig %s: %s", onig_object, str);
197    SLang_free_slstring (str);
198    return NULL;
199 }
200 
get_onig_names(Name_Map_Type * map)201 static void get_onig_names (Name_Map_Type *map)
202 {
203    SLindex_Type i, num;
204    SLang_Array_Type *at;
205    char **names;
206    Name_Map_Type *table;
207 
208    table = map;
209    while (table->name != NULL)
210      table++;
211    num = (SLindex_Type) (table - map);
212 
213    if (NULL == (at = SLang_create_array (SLANG_STRING_TYPE, 0, NULL, &num, 1)))
214      return;
215 
216    table = map;
217    names = (char **)at->data;
218    for (i = 0; i < num; i++)
219      {
220 	if (NULL == (names[i] = SLang_create_slstring (table->name)))
221 	  {
222 	     SLang_free_array (at);
223 	     return;
224 	  }
225 	table++;
226      }
227    (void) SLang_push_array (at, 1);
228 }
229 
230 Syntax_Table_Map_Type Syntax_Table_Map [] =
231 {
232    { "asis", ONIG_SYNTAX_ASIS },
233    { "posix_basic", ONIG_SYNTAX_POSIX_BASIC },
234    { "posix_extended", ONIG_SYNTAX_POSIX_EXTENDED },
235    { "emacs", ONIG_SYNTAX_EMACS },
236    { "grep", ONIG_SYNTAX_GREP },
237    { "gnu_regex", ONIG_SYNTAX_GNU_REGEX },
238    { "java", ONIG_SYNTAX_JAVA },
239    { "perl", ONIG_SYNTAX_PERL },
240    { "perl_ng", ONIG_SYNTAX_PERL_NG },
241    { "ruby", ONIG_SYNTAX_RUBY },
242    { NULL, NULL}
243 };
244 
pop_onig_syntax(void)245 static OnigSyntaxType *pop_onig_syntax (void)
246 {
247    return (OnigSyntaxType *) pop_onig_name_ptr ((Name_Map_Type *)Syntax_Table_Map, "syntax");
248 }
249 
250 static Encoding_Table_Map_Type Encoding_Table_Map [] =
251 {
252 #ifdef ONIG_ENCODING_ASCII
253    {"ascii", ONIG_ENCODING_ASCII},
254 #endif
255 #ifdef ONIG_ENCODING_ISO_8859_1
256    {"iso_8859_1", ONIG_ENCODING_ISO_8859_1},
257 #endif
258 #ifdef ONIG_ENCODING_ISO_8859_2
259    {"iso_8859_2", ONIG_ENCODING_ISO_8859_2},
260 #endif
261 #ifdef ONIG_ENCODING_ISO_8859_3
262    {"iso_8859_3", ONIG_ENCODING_ISO_8859_3},
263 #endif
264 #ifdef ONIG_ENCODING_ISO_8859_4
265    {"iso_8859_4", ONIG_ENCODING_ISO_8859_4},
266 #endif
267 #ifdef ONIG_ENCODING_ISO_8859_5
268    {"iso_8859_5", ONIG_ENCODING_ISO_8859_5},
269 #endif
270 #ifdef ONIG_ENCODING_ISO_8859_6
271    {"iso_8859_6", ONIG_ENCODING_ISO_8859_6},
272 #endif
273 #ifdef ONIG_ENCODING_ISO_8859_7
274    {"iso_8859_7", ONIG_ENCODING_ISO_8859_7},
275 #endif
276 #ifdef ONIG_ENCODING_ISO_8859_8
277    {"iso_8859_8", ONIG_ENCODING_ISO_8859_8},
278 #endif
279 #ifdef ONIG_ENCODING_ISO_8859_9
280    {"iso_8859_9", ONIG_ENCODING_ISO_8859_9},
281 #endif
282 #ifdef ONIG_ENCODING_ISO_8859_10
283    {"iso_8859_10", ONIG_ENCODING_ISO_8859_10},
284 #endif
285 #ifdef ONIG_ENCODING_ISO_8859_11
286    {"iso_8859_11", ONIG_ENCODING_ISO_8859_11},
287 #endif
288 #ifdef ONIG_ENCODING_ISO_8859_13
289    {"iso_8859_13", ONIG_ENCODING_ISO_8859_13},
290 #endif
291 #ifdef ONIG_ENCODING_ISO_8859_14
292    {"iso_8859_14", ONIG_ENCODING_ISO_8859_14},
293 #endif
294 #ifdef ONIG_ENCODING_ISO_8859_15
295    {"iso_8859_15", ONIG_ENCODING_ISO_8859_15},
296 #endif
297 #ifdef ONIG_ENCODING_ISO_8859_16
298    {"iso_8859_16", ONIG_ENCODING_ISO_8859_16},
299 #endif
300 #ifdef ONIG_ENCODING_UTF8
301    {"utf8", ONIG_ENCODING_UTF8},
302 #endif
303 #ifdef ONIG_ENCODING_UTF16_BE
304    {"utf16_be", ONIG_ENCODING_UTF16_BE},
305 #endif
306 #ifdef ONIG_ENCODING_UTF16_LE
307    {"utf16_le", ONIG_ENCODING_UTF16_LE},
308 #endif
309 #ifdef ONIG_ENCODING_UTF32_BE
310    {"utf32_be", ONIG_ENCODING_UTF32_BE},
311 #endif
312 #ifdef ONIG_ENCODING_UTF32_LE
313    {"utf32_le", ONIG_ENCODING_UTF32_LE},
314 #endif
315 #ifdef ONIG_ENCODING_EUC_JP
316    {"euc_jp", ONIG_ENCODING_EUC_JP},
317 #endif
318 #ifdef ONIG_ENCODING_EUC_TW
319    {"euc_tw", ONIG_ENCODING_EUC_TW},
320 #endif
321 #ifdef ONIG_ENCODING_EUC_KR
322    {"euc_kr", ONIG_ENCODING_EUC_KR},
323 #endif
324 #ifdef ONIG_ENCODING_EUC_CN
325    {"euc_cn", ONIG_ENCODING_EUC_CN},
326 #endif
327 #ifdef ONIG_ENCODING_SJIS
328    {"sjis", ONIG_ENCODING_SJIS},
329 #endif
330 #ifdef ONIG_ENCODING_KOI8
331    /* {"koi8", ONIG_ENCODING_KOI8}, */
332 #endif
333 #ifdef ONIG_ENCODING_KOI8_R
334    {"koi8_r", ONIG_ENCODING_KOI8_R},
335 #endif
336 #ifdef ONIG_ENCODING_CP1251
337    {"cp1251", ONIG_ENCODING_CP1251},
338 #endif
339 #ifdef ONIG_ENCODING_BIG5
340    {"big5", ONIG_ENCODING_BIG5},
341 #endif
342 #ifdef ONIG_ENCODING_GB18030
343    {"gb18030", ONIG_ENCODING_GB18030},
344 #endif
345    {NULL, NULL}
346 };
347 
pop_onig_encoding(void)348 static OnigEncodingType *pop_onig_encoding (void)
349 {
350    return (OnigEncodingType *) pop_onig_name_ptr ((Name_Map_Type *)Encoding_Table_Map, "encoding");
351 }
352 
353 typedef struct
354 {
355    regex_t *re;
356    OnigRegion *region;
357    int match_pos;		       /* >= 0 if ok */
358 }
359 Onig_Type;
360 
free_onig_type(Onig_Type * o)361 static void free_onig_type (Onig_Type *o)
362 {
363    if (o == NULL)
364      return;
365    if (o->region != NULL)
366      onig_region_free (o->region, 1);
367    if (o->re != NULL)
368      onig_free (o->re);
369    SLfree ((char *) o);
370 }
371 
push_onig_type(Onig_Type * o)372 static int push_onig_type (Onig_Type *o)
373 {
374    SLang_MMT_Type *mmt;
375 
376    if (NULL == (mmt = SLang_create_mmt (Onig_Type_Id, (VOID_STAR) o)))
377      {
378 	free_onig_type (o);
379 	return -1;
380      }
381    if (-1 == SLang_push_mmt (mmt))
382      {
383 	SLang_free_mmt (mmt);
384 	return -1;
385      }
386    return 0;
387 }
388 
pop_onig_option(OnigOptionType * optp)389 static int pop_onig_option (OnigOptionType *optp)
390 {
391    int iopt;
392 
393    if (-1 == SLang_pop_int (&iopt))
394      return -1;
395    *optp = (OnigOptionType) iopt;
396    return 0;
397 }
398 
399 /* Usage: reg = onig_new (pattern, options, enc, syntax) */
do_onig_new(void)400 static void do_onig_new (void)
401 {
402    const UChar* pattern;
403    const UChar* pattern_end;
404    OnigOptionType option;
405    OnigEncoding enc;
406    OnigSyntaxType *syntax;
407    OnigErrorInfo err_info;
408    Onig_Type *o;
409    int status;
410 
411    syntax = ONIG_SYNTAX_PERL;
412    if (SLinterp_is_utf8_mode ())
413      enc = ONIG_ENCODING_UTF8;
414    else
415      enc = ONIG_ENCODING_ISO_8859_1;
416    option = ONIG_OPTION_DEFAULT;
417 
418    switch (SLang_Num_Function_Args)
419      {
420       default:
421 	SLang_verror (SL_Usage_Error, "Usage: r = onig_new (pattern [,options [,encoding [,syntax]]])");
422 	return;
423 
424       case 4:
425 	if (NULL == (syntax = pop_onig_syntax ()))
426 	  return;
427       case 3:
428 	if (NULL == (enc = pop_onig_encoding ()))
429 	  return;
430       case 2:
431 	if (-1 == pop_onig_option (&option))
432 	  return;
433       case 1:
434 	if (-1 == SLang_pop_slstring ((char **)&pattern))
435 	  return;
436      }
437 
438    if (NULL == (o = (Onig_Type *) SLcalloc (1, sizeof (Onig_Type))))
439      {
440 	SLang_free_slstring ((char *)pattern);
441 	return;
442      }
443 
444    pattern_end = pattern + strlen ((char *)pattern);
445 
446    status = onig_new (&o->re, pattern, pattern_end,
447 		      option, enc, syntax, &err_info);
448 
449    if (status != ONIG_NORMAL)
450      {
451 	throw_onig_error (status, &err_info);
452 	SLang_free_slstring ((char *)pattern);
453 	free_onig_type (o);
454 	return;
455      }
456 
457    if (NULL == (o->region = onig_region_new ()))
458      {
459 	SLang_verror (slOnig_Error, "failed to allocate a region");
460 	SLang_free_slstring ((char *)pattern);
461 	free_onig_type (o);
462 	return;
463      }
464 
465    SLang_free_slstring ((char *)pattern);
466    (void) push_onig_type (o);	       /* frees it */
467 }
468 
do_onig_search_internal(Onig_Type * o,OnigOptionType option,UChar * str,UChar * str_end,int start_pos,int end_pos)469 static int do_onig_search_internal (Onig_Type *o, OnigOptionType option, UChar *str, UChar *str_end, int start_pos, int end_pos)
470 {
471    UChar *start, *range;
472    int status;
473 
474    onig_region_clear (o->region);
475 
476    start = str + start_pos;
477    range = str + end_pos;
478    /* fwd search: (start <= search string < range)
479     * bkw search: (range <= search string <= start)
480     */
481    if ((start < str) || (start > str_end)
482        || (range < str) || (range > str_end))
483      {
484 	SLang_verror (SL_InvalidParm_Error, "Invalid string offsets");
485 	return -1;
486      }
487    status = onig_search (o->re, str, str_end, start, range, o->region, option);
488 
489    if (status >= 0)
490      return status;
491 
492    if (status == ONIG_MISMATCH)
493      return -1;
494 
495    throw_onig_error (status, NULL);
496    return -2;
497 }
498 
499 /* Usage: onig_search (o, str [start, end] [,option]) */
do_onig_search(void)500 static int do_onig_search (void)
501 {
502    int start_pos = 0, end_pos = -1;
503    char *str, *str_end;
504    SLang_BString_Type *bstr = NULL;
505    Onig_Type *o;
506    SLang_MMT_Type *mmt;
507    int status = -1;
508    OnigOptionType option = ONIG_OPTION_NONE;
509 
510    switch (SLang_Num_Function_Args)
511      {
512       default:
513 	SLang_verror (SL_Usage_Error, "Usage: n = onig_search (compiled_pattern, str [,start_ofs, end_ofs] [,option])");
514 	return -1;
515 
516       case 5:
517 	if (-1 == pop_onig_option (&option))
518 	  return -1;
519 	/* drop */
520       case 4:
521 	if (-1 == SLang_pop_int (&end_pos))
522 	  return -1;
523 	if (-1 == SLang_pop_int (&start_pos))
524 	  return -1;
525 	break;
526       case 3:
527 	if (-1 == pop_onig_option (&option))
528 	  return -1;
529 	if (option & ~(ONIG_OPTION_NOTBOL|ONIG_OPTION_NOTEOL))
530 	  {
531 	     SLang_verror (SL_InvalidParm_Error, "onig_search: invalid option flags");
532 	     return -1;
533 	  }
534 	break;
535       case 2:
536 	 break;
537      }
538 
539    switch(SLang_peek_at_stack())
540      {
541       case SLANG_STRING_TYPE:
542 	if (-1 == SLang_pop_slstring (&str))
543 	  return -1;
544 	str_end = str + strlen (str);
545 	break;
546 
547       case SLANG_BSTRING_TYPE:
548       default:
549 	  {
550 	     SLstrlen_Type len;
551 
552 	     if (-1 == SLang_pop_bstring(&bstr))
553 	       return -1;
554 
555 	     str = (char *)SLbstring_get_pointer(bstr, &len);
556 	     if (str == NULL)
557 	       {
558 		  SLbstring_free (bstr);
559 		  return -1;
560 	       }
561 	     str_end = str + len;
562 	  }
563 	break;
564      }
565 
566    if (end_pos < 0)
567      end_pos = (int) (str_end - str);
568 
569    if (NULL == (mmt = SLang_pop_mmt (Onig_Type_Id)))
570      goto free_and_return;
571    o = (Onig_Type *)SLang_object_from_mmt (mmt);
572 
573    status = do_onig_search_internal (o, option, (UChar *)str, (UChar *)str_end, start_pos, end_pos);
574    if (status >= 0)
575      {
576 	o->match_pos = status;
577 	status = o->region->num_regs;
578 	goto free_and_return;
579      }
580    o->match_pos = -1;
581 
582    if (status == -1)
583      {				       /* no match */
584 	status = 0;
585 	goto free_and_return;
586      }
587 
588    /* Else an error occurred */
589    /* drop */
590 
591 free_and_return:
592 
593    SLang_free_mmt (mmt);
594    if (bstr != NULL)
595      SLbstring_free (bstr);
596    else
597      SLang_free_slstring (str);
598 
599    return status;
600 }
601 
get_nth_start_stop(Onig_Type * o,unsigned int n,SLstrlen_Type * a,SLstrlen_Type * b)602 static int get_nth_start_stop (Onig_Type *o, unsigned int n,
603 			       SLstrlen_Type *a, SLstrlen_Type *b)
604 {
605    if (o->match_pos < 0)
606      {
607 	SLang_verror (SL_InvalidParm_Error, "The last match was unsuccessful");
608 	return -1;
609      }
610    if (n >= (unsigned int) o->region->num_regs)
611      return -1;
612 
613    *a = (SLstrlen_Type) o->region->beg[n];
614    *b = (SLstrlen_Type) o->region->end[n];
615    return 0;
616 }
617 
nth_match(Onig_Type * o,int * np)618 static void nth_match (Onig_Type *o, int *np)
619 {
620    SLstrlen_Type start, stop;
621    SLang_Array_Type *at;
622    SLindex_Type two = 2;
623    int *data;
624 
625    if (-1 == get_nth_start_stop (o, (unsigned int) *np, &start, &stop))
626      {
627 	SLang_push_null ();
628 	return;
629      }
630 
631    if (NULL == (at = SLang_create_array (SLANG_INT_TYPE, 0, NULL, &two, 1)))
632      return;
633 
634    data = (int *)at->data;
635    data[0] = (int)start;
636    data[1] = (int)stop;
637    (void) SLang_push_array (at, 1);
638 }
639 
nth_substr(Onig_Type * o,char * str,int * np)640 static void nth_substr (Onig_Type *o, char *str, int *np)
641 {
642    SLstrlen_Type start, stop;
643    SLstrlen_Type len;
644 
645    len = strlen (str);
646 
647    if ((-1 == get_nth_start_stop (o, (unsigned int) *np, &start, &stop))
648        || (start > len) || (stop > len))
649      {
650 	SLang_push_null ();
651 	return;
652      }
653 
654    str = SLang_create_nslstring (str + start, stop - start);
655    (void) SLang_push_string (str);
656    SLang_free_slstring (str);
657 }
658 
659 static SLang_Name_Type *Warn_Func;
660 static SLang_Name_Type *Verb_Warn_Func;
661 
warn_func(const char * msg)662 static void warn_func (const char *msg)
663 {
664    if (Warn_Func != NULL)
665      {
666 	if (0 == SLang_push_string ((char *) msg))
667 	  SLexecute_function (Warn_Func);
668      }
669 }
670 
verb_warn_func(const char * msg)671 static void verb_warn_func (const char *msg)
672 {
673    if (Verb_Warn_Func != NULL)
674      {
675 	if (0 == SLang_push_string ((char *) msg))
676 	  SLexecute_function (Verb_Warn_Func);
677      }
678 }
679 
set_warn_func(void)680 static void set_warn_func (void)
681 {
682    SLang_Name_Type *sf;
683 
684    if (NULL == (sf = SLang_pop_function ()))
685      return;
686 
687    if (Warn_Func != NULL)
688      SLang_free_function (Warn_Func);
689 
690    Warn_Func = sf;
691 }
692 
set_verb_warn_func(void)693 static void set_verb_warn_func (void)
694 {
695    SLang_Name_Type *sf;
696 
697    if (NULL == (sf = SLang_pop_function ()))
698      return;
699 
700    if (Verb_Warn_Func != NULL)
701      SLang_free_function (Verb_Warn_Func);
702 
703    Verb_Warn_Func = sf;
704 }
705 
do_onig_version(void)706 static char *do_onig_version (void)
707 {
708    return (char *)onig_version ();
709 }
710 
get_encodings(void)711 static void get_encodings (void)
712 {
713    get_onig_names ((Name_Map_Type *)Encoding_Table_Map);
714 }
715 
get_syntaxes(void)716 static void get_syntaxes (void)
717 {
718    get_onig_names ((Name_Map_Type *) Syntax_Table_Map);
719 }
720 
721 static SLang_IConstant_Type Onig_Consts [] =
722 {
723    MAKE_ICONSTANT ("ONIG_OPTION_DEFAULT", ONIG_OPTION_DEFAULT),
724    MAKE_ICONSTANT ("ONIG_OPTION_NONE", ONIG_OPTION_NONE),
725    MAKE_ICONSTANT ("ONIG_OPTION_SINGLELINE", ONIG_OPTION_SINGLELINE),
726    MAKE_ICONSTANT ("ONIG_OPTION_MULTILINE", ONIG_OPTION_MULTILINE),
727    MAKE_ICONSTANT ("ONIG_OPTION_IGNORECASE", ONIG_OPTION_IGNORECASE),
728    MAKE_ICONSTANT ("ONIG_OPTION_EXTEND", ONIG_OPTION_EXTEND),
729    MAKE_ICONSTANT ("ONIG_OPTION_FIND_LONGEST", ONIG_OPTION_FIND_LONGEST),
730    MAKE_ICONSTANT ("ONIG_OPTION_FIND_NOT_EMPTY", ONIG_OPTION_FIND_NOT_EMPTY),
731    MAKE_ICONSTANT ("ONIG_OPTION_NEGATE_SINGLELINE", ONIG_OPTION_NEGATE_SINGLELINE),
732    MAKE_ICONSTANT ("ONIG_OPTION_DONT_CAPTURE_GROUP", ONIG_OPTION_DONT_CAPTURE_GROUP),
733    MAKE_ICONSTANT ("ONIG_OPTION_CAPTURE_GROUP", ONIG_OPTION_CAPTURE_GROUP),
734 
735    MAKE_ICONSTANT ("ONIG_OPTION_NOTBOL", ONIG_OPTION_NOTBOL),
736    MAKE_ICONSTANT ("ONIG_OPTION_NOTEOL", ONIG_OPTION_NOTEOL),
737 
738    SLANG_END_ICONST_TABLE
739 };
740 
741 #define DUMMY_ONIG_TYPE 0
742 #define O DUMMY_ONIG_TYPE
743 #define I SLANG_INT_TYPE
744 #define V SLANG_VOID_TYPE
745 #define S SLANG_STRING_TYPE
746 static SLang_Intrin_Fun_Type Onig_Intrinsics [] =
747 {
748    MAKE_INTRINSIC_0("onig_version", do_onig_version, S),
749    MAKE_INTRINSIC_0("onig_new", do_onig_new, V),
750    MAKE_INTRINSIC_0("onig_search", do_onig_search, I),
751    MAKE_INTRINSIC_2("onig_nth_match", nth_match, V, O, I),
752    MAKE_INTRINSIC_3("onig_nth_substr", nth_substr, V, O, S, I),
753    MAKE_INTRINSIC_0("onig_set_warn_func", set_warn_func, V),
754    MAKE_INTRINSIC_0("onig_set_verb_warn_func", set_verb_warn_func, V),
755    MAKE_INTRINSIC_0("onig_get_encodings", get_encodings, V),
756    MAKE_INTRINSIC_0("onig_get_syntaxes", get_syntaxes, V),
757    /* MAKE_INTRINSIC_1("slang_to_pcre", slang_to_pcre, V, S), */
758    SLANG_END_INTRIN_FUN_TABLE
759 };
760 #undef V
761 #undef S
762 #undef I
763 #undef O
764 
destroy_onig(SLtype type,VOID_STAR f)765 static void destroy_onig (SLtype type, VOID_STAR f)
766 {
767    (void) type;
768 
769    free_onig_type ((Onig_Type *)f);
770 }
771 
register_onig_type(void)772 static int register_onig_type (void)
773 {
774    SLang_Class_Type *cl;
775 
776    if (Onig_Type_Id != 0)
777      return 0;
778 
779    if (NULL == (cl = SLclass_allocate_class ("Onig_Type")))
780      return -1;
781 
782    if (-1 == SLclass_set_destroy_function (cl, destroy_onig))
783      return -1;
784 
785    /* By registering as SLANG_VOID_TYPE, slang will dynamically allocate a
786     * type.
787     */
788    if (-1 == SLclass_register_class (cl, SLANG_VOID_TYPE, sizeof (Onig_Type), SLANG_CLASS_TYPE_MMT))
789      return -1;
790 
791    Onig_Type_Id = SLclass_get_class_id (cl);
792 
793    if (-1 == SLclass_patch_intrin_fun_table1 (Onig_Intrinsics, DUMMY_ONIG_TYPE, Onig_Type_Id))
794      return -1;
795 
796    return 0;
797 }
798 
setup_onig(void)799 static int setup_onig (void)
800 {
801    static int inited = 0;
802 
803    if (inited)
804      return 0;
805 
806    if ((-1 == slOnig_Error)
807        && (-1 == (slOnig_Error = SLerr_new_exception (SL_RunTime_Error, "OnigError", "Onig Error"))))
808      return -1;
809 
810    if (-1 == onig_init ())
811      {
812 	SLang_verror (slOnig_Error, "onig_init failed");
813 	return -1;
814      }
815 
816    onig_set_warn_func (&warn_func);
817    onig_set_verb_warn_func (&verb_warn_func);
818    onig_set_default_syntax (ONIG_SYNTAX_PERL);
819 
820    inited = 1;
821 
822    return 0;
823 }
824 
init_onig_module_ns(char * ns_name)825 int init_onig_module_ns (char *ns_name)
826 {
827    SLang_NameSpace_Type *ns = SLns_create_namespace (ns_name);
828    if (ns == NULL)
829      return -1;
830 
831    if (-1 == setup_onig ())
832      return -1;
833    if (-1 == register_onig_type ())
834      return -1;
835 
836    if ((-1 == SLns_add_intrin_fun_table (ns, Onig_Intrinsics, "__ONIG__"))
837        || (-1 == SLns_add_iconstant_table (ns, Onig_Consts, NULL)))
838      return -1;
839 
840    return 0;
841 }
842 
843 /* This function is optional */
deinit_onig_module(void)844 void deinit_onig_module (void)
845 {
846    (void) onig_end ();
847 }
848 
849