1 /*
2  * echo.c
3  */
4 #include <stdlib.h>
5 #include <stdio.h>
6 #include <string.h>
7 #include "oniguruma.h"
8 
9 static int
echo(OnigCalloutArgs * args,void * user_data)10 echo(OnigCalloutArgs* args, void* user_data)
11 {
12   int r;
13   OnigCalloutIn in;
14   OnigType type;
15   OnigValue val;
16   FILE* fp;
17 
18   fp = stdout;
19 
20   in = onig_get_callout_in_by_callout_args(args);
21 
22   r = onig_get_arg_by_callout_args(args, 1, &type, &val);
23   if (r != ONIG_NORMAL) return r;
24 
25   if (in == ONIG_CALLOUT_IN_PROGRESS) {
26     if (val.c == '<')
27       return ONIG_CALLOUT_SUCCESS;
28   }
29   else {
30     if (val.c != 'X' && val.c != '<')
31       return ONIG_CALLOUT_SUCCESS;
32   }
33 
34   r = onig_get_arg_by_callout_args(args, 0, &type, &val);
35   if (r != ONIG_NORMAL) return r;
36 
37 
38   fprintf(fp, "%s %s\n",
39           (in == ONIG_CALLOUT_IN_PROGRESS ? "=>" : "<="),
40           val.s.start);
41   fflush(fp);
42 
43   return ONIG_CALLOUT_SUCCESS;
44 }
45 
46 
47 static int
test(OnigEncoding enc,char * in_pattern,char * in_str)48 test(OnigEncoding enc, char* in_pattern, char* in_str)
49 {
50   int r;
51   unsigned char *start, *range, *end;
52   regex_t* reg;
53   OnigErrorInfo einfo;
54   OnigRegion *region;
55   UChar* pattern;
56   UChar* str;
57 
58   pattern = (UChar* )in_pattern;
59   str = (UChar* )in_str;
60 
61   r = onig_new(&reg, pattern, pattern + strlen((char* )pattern),
62                ONIG_OPTION_DEFAULT, enc, ONIG_SYNTAX_DEFAULT, &einfo);
63   if (r != ONIG_NORMAL) {
64     char s[ONIG_MAX_ERROR_MESSAGE_LEN];
65     onig_error_code_to_str((UChar* )s, r, &einfo);
66     fprintf(stderr, "COMPILE ERROR: %d: %s\n", r, s);
67     return -1;
68   }
69 
70   region = onig_region_new();
71 
72   end   = str + strlen((char* )str);
73   start = str;
74   range = end;
75   r = onig_search(reg, str, end, start, range, region, ONIG_OPTION_NONE);
76   if (r >= 0) {
77     int i;
78 
79     fprintf(stderr, "match at %d\n", r);
80     for (i = 0; i < region->num_regs; i++) {
81       fprintf(stderr, "%d: (%d-%d)\n", i, region->beg[i], region->end[i]);
82     }
83   }
84   else if (r == ONIG_MISMATCH) {
85     fprintf(stderr, "search fail\n");
86   }
87   else { /* error */
88     char s[ONIG_MAX_ERROR_MESSAGE_LEN];
89     onig_error_code_to_str((UChar* )s, r);
90     fprintf(stderr, "SEARCH ERROR: %d: %s\n", r, s);
91   }
92 
93   onig_region_free(region, 1 /* 1:free self, 0:free contents only */);
94   onig_free(reg);
95   return r;
96 }
97 
main(int argc,char * argv[])98 extern int main(int argc, char* argv[])
99 {
100   int r;
101   int id;
102   UChar* name;
103   OnigEncoding use_encs[1];
104   OnigType arg_types[4];
105   OnigValue opt_defaults[4];
106   OnigEncoding enc;
107 
108   enc = ONIG_ENCODING_UTF8;
109   use_encs[0] = enc;
110 
111   r = onig_initialize(use_encs, sizeof(use_encs)/sizeof(use_encs[0]));
112   if (r != ONIG_NORMAL) return -1;
113 
114   name = (UChar* )"echo";
115   arg_types[0] = ONIG_TYPE_STRING;
116   arg_types[1] = ONIG_TYPE_CHAR;
117   opt_defaults[0].s.start = (UChar* )"echo";
118   opt_defaults[0].s.end   = opt_defaults[0].s.start +
119                                 strlen((char* )opt_defaults[0].s.start);
120   opt_defaults[1].c = '>';
121 
122   id = onig_set_callout_of_name(enc, ONIG_CALLOUT_TYPE_SINGLE,
123                                 name, name + strlen((char* )name),
124                                 ONIG_CALLOUT_IN_BOTH, echo, 0,
125                                 2, arg_types, 2, opt_defaults);
126   if (id < 0) {
127     fprintf(stderr, "ERROR: fail to set callout of name: %s\n", name);
128     return -1;
129   }
130 
131   test(enc, "(?:(*echo{abc!!!})a|b)*", "abba");
132   test(enc, "(?:(*echo{xyz,X})a|b)*", "abba");
133 
134   onig_end();
135   return 0;
136 }
137