Commit | Line | Data |
---|---|---|
d44e3c4f | 1 | /****************************************************************************** |
2 | * Copyright (c) 2000-2016 Ericsson Telecom AB | |
3 | * All rights reserved. This program and the accompanying materials | |
4 | * are made available under the terms of the Eclipse Public License v1.0 | |
5 | * which accompanies this distribution, and is available at | |
6 | * http://www.eclipse.org/legal/epl-v10.html | |
7 | * | |
8 | * Contributors: | |
9 | * Balasko, Jeno | |
10 | * Delic, Adam | |
11 | * Raduly, Csaba | |
12 | * Szabados, Kristof | |
13 | * Szabo, Janos Zoltan – initial implementation | |
14 | * Szalai, Gabor | |
15 | * | |
16 | ******************************************************************************/ | |
970ed795 EL |
17 | #include <string.h> |
18 | #include <sys/types.h> | |
19 | #include <regex.h> | |
20 | #include "../common/memory.h" | |
21 | #include "../common/pattern.hh" | |
22 | #include "TEXT.hh" | |
23 | #include "Addfunc.hh" | |
24 | #include "Logger.hh" | |
25 | #include "Integer.hh" | |
26 | #include "Charstring.hh" | |
27 | #define ERRMSG_BUFSIZE2 500 | |
28 | ||
29 | Token_Match::Token_Match(const char *posix_str, boolean case_sensitive, | |
30 | boolean fixed) | |
31 | : posix_regexp_begin() | |
32 | , posix_regexp_first() | |
33 | , token_str(posix_str) | |
34 | , fixed_len(0) | |
35 | , null_match(FALSE) | |
36 | { | |
37 | if (posix_str == NULL || posix_str[0] == '\0') { | |
38 | token_str = ""; | |
39 | null_match = TRUE; | |
40 | return; | |
41 | } | |
42 | ||
43 | if (fixed) { | |
44 | // no regexp | |
45 | fixed_len = strlen(posix_str); | |
46 | ||
47 | if (!case_sensitive) { | |
48 | // Can't happen. The compiler should always generate | |
49 | // case sensitive matching for fixed strings. | |
50 | TTCN_EncDec_ErrorContext::error_internal( | |
51 | "Case insensitive fixed string matching not implemented"); | |
52 | } | |
53 | } | |
54 | else { | |
55 | int regcomp_flags = REG_EXTENDED; | |
56 | if (!case_sensitive) regcomp_flags |= REG_ICASE; | |
57 | int ret_val = regcomp(&posix_regexp_begin, posix_str, regcomp_flags); | |
58 | if (ret_val != 0) { | |
59 | char msg[ERRMSG_BUFSIZE2]; | |
60 | regerror(ret_val, &posix_regexp_begin, msg, ERRMSG_BUFSIZE2); | |
61 | TTCN_error("Internal error: regcomp() failed on posix_regexp_begin when " | |
62 | "constructing Token_Match: %s", msg); | |
63 | } | |
64 | ret_val = regcomp(&posix_regexp_first, posix_str + 1, regcomp_flags); | |
65 | if (ret_val != 0) { | |
66 | regfree(&posix_regexp_begin); | |
67 | char msg[ERRMSG_BUFSIZE2]; | |
68 | regerror(ret_val, &posix_regexp_first, msg, ERRMSG_BUFSIZE2); | |
69 | TTCN_error("Internal error: regcomp() failed on posix_regexp_first when " | |
70 | "constructing Token_Match: %s", msg); | |
71 | } | |
72 | } | |
73 | } | |
74 | ||
75 | Token_Match::~Token_Match() | |
76 | { | |
77 | if (!null_match && fixed_len == 0) { | |
78 | regfree(&posix_regexp_begin); | |
79 | regfree(&posix_regexp_first); | |
80 | } | |
81 | } | |
82 | ||
83 | int Token_Match::match_begin(TTCN_Buffer& buff) const | |
84 | { | |
85 | int retval=-1; | |
86 | int ret_val=-1; | |
87 | if(null_match){ | |
88 | if (TTCN_EncDec::get_error_behavior(TTCN_EncDec::ET_LOG_MATCHING) != | |
89 | TTCN_EncDec::EB_IGNORE) { | |
90 | char msg[ERRMSG_BUFSIZE2]; | |
91 | regerror(ret_val, &posix_regexp_begin, msg, ERRMSG_BUFSIZE2); | |
92 | TTCN_Logger::log(TTCN_Logger::DEBUG_ENCDEC, "match_begin data: %s", | |
93 | (const char*)buff.get_read_data()); | |
94 | TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC); | |
95 | TTCN_Logger::log_event_str("match_begin token: null_match"); | |
96 | TTCN_Logger::end_event(); | |
97 | TTCN_Logger::log(TTCN_Logger::DEBUG_ENCDEC, "match_begin result: 0"); | |
98 | } | |
99 | ||
100 | return 0; | |
101 | } | |
102 | if (fixed_len != 0) { // | |
103 | retval=strncmp((const char*)buff.get_read_data(), token_str, fixed_len) | |
104 | ? -1 // not matched | |
105 | : fixed_len; | |
106 | } else { | |
107 | regmatch_t pmatch[2]; | |
108 | ret_val=regexec(&posix_regexp_begin,(const char*)buff.get_read_data(), | |
109 | 2, pmatch, 0); | |
110 | if(ret_val==0) { | |
111 | retval=pmatch[1].rm_eo-pmatch[1].rm_so; // pmatch[1] is the capture group | |
112 | } else if (ret_val==REG_NOMATCH) { | |
113 | retval=-1; | |
114 | } else { | |
115 | /* regexp error */ | |
116 | char msg[ERRMSG_BUFSIZE2]; | |
117 | regerror(ret_val, &posix_regexp_begin, msg, ERRMSG_BUFSIZE2); | |
118 | TTCN_error("Internal error: regexec() failed in " | |
119 | "Token_Match::match_begin(): %s", msg); | |
120 | } | |
121 | } | |
122 | if (TTCN_EncDec::get_error_behavior(TTCN_EncDec::ET_LOG_MATCHING) != | |
123 | TTCN_EncDec::EB_IGNORE) { | |
124 | TTCN_Logger::log(TTCN_Logger::DEBUG_ENCDEC, "match_begin data: %s", | |
125 | (const char*)buff.get_read_data()); | |
126 | TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC); | |
127 | TTCN_Logger::log_event_str("match_begin token: \""); | |
128 | for (size_t i = 0; token_str[i] != '\0'; i++) | |
129 | TTCN_Logger::log_char_escaped(token_str[i]); | |
130 | TTCN_Logger::log_char('"'); | |
131 | TTCN_Logger::end_event(); | |
132 | if(fixed_len == 0){ | |
133 | char msg[ERRMSG_BUFSIZE2]; | |
134 | regerror(ret_val, &posix_regexp_begin, msg, ERRMSG_BUFSIZE2); | |
135 | TTCN_Logger::log(TTCN_Logger::DEBUG_ENCDEC, "match_begin regexec result: %d, %s", | |
136 | ret_val,msg); | |
137 | } | |
138 | TTCN_Logger::log(TTCN_Logger::DEBUG_ENCDEC, "match_begin result: %d", | |
139 | retval); | |
140 | } | |
141 | return retval; | |
142 | } | |
143 | ||
144 | int Token_Match::match_first(TTCN_Buffer& buff) const | |
145 | { | |
146 | int retval=-1; | |
147 | int ret_val=-1; | |
148 | if(null_match){ | |
149 | if (TTCN_EncDec::get_error_behavior(TTCN_EncDec::ET_LOG_MATCHING) != | |
150 | TTCN_EncDec::EB_IGNORE) { | |
151 | char msg[ERRMSG_BUFSIZE2]; | |
152 | regerror(ret_val, &posix_regexp_begin, msg, ERRMSG_BUFSIZE2); | |
153 | TTCN_Logger::log(TTCN_Logger::DEBUG_ENCDEC, "match_first data: %s", | |
154 | (const char*)buff.get_read_data()); | |
155 | TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC); | |
156 | TTCN_Logger::log_event_str("match_first token: null_match"); | |
157 | TTCN_Logger::end_event(); | |
158 | TTCN_Logger::log(TTCN_Logger::DEBUG_ENCDEC, "match_first result: 0"); | |
159 | } | |
160 | ||
161 | return 0; | |
162 | } | |
163 | //TTCN_Logger::log(TTCN_Logger::DEBUG_ENCDEC,"match_first data: %s\n\r",(const char*)buff.get_read_data()); | |
164 | //TTCN_Logger::log(TTCN_Logger::DEBUG_ENCDEC,"match_first token: %s\n\r",token); | |
165 | if (fixed_len != 0) { | |
166 | const char *haystack = (const char*)buff.get_read_data(); | |
167 | const char *pos = strstr(haystack, token_str); // TODO smarter search: Boyer-Moore / Shift-Or | |
168 | retval = (pos == NULL) ? -1 : (pos - haystack); | |
169 | } else { | |
170 | regmatch_t pmatch[2]; | |
171 | ret_val=regexec(&posix_regexp_first,(const char*)buff.get_read_data(), | |
172 | 2, pmatch, REG_NOTBOL); | |
173 | if(ret_val==0) { | |
174 | retval=pmatch[1].rm_so; | |
175 | } else if (ret_val==REG_NOMATCH) { | |
176 | retval=-1; | |
177 | } else { | |
178 | /* regexp error */ | |
179 | char msg[ERRMSG_BUFSIZE2]; | |
180 | regerror(ret_val, &posix_regexp_begin, msg, ERRMSG_BUFSIZE2); | |
181 | TTCN_error("Internal error: regexec() failed in " | |
182 | "Token_Match::match_first(): %s", msg); | |
183 | } | |
184 | } | |
185 | if (TTCN_EncDec::get_error_behavior(TTCN_EncDec::ET_LOG_MATCHING) != | |
186 | TTCN_EncDec::EB_IGNORE) { | |
187 | TTCN_Logger::log(TTCN_Logger::DEBUG_ENCDEC, "match_first data: %s", | |
188 | (const char*)buff.get_read_data()); | |
189 | TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC); | |
190 | TTCN_Logger::log_event_str("match_first token: \""); | |
191 | for (size_t i = 0; token_str[i] != '\0'; i++) | |
192 | TTCN_Logger::log_char_escaped(token_str[i]); | |
193 | TTCN_Logger::log_char('"'); | |
194 | TTCN_Logger::end_event(); | |
195 | if (fixed_len == 0) { | |
196 | char msg[ERRMSG_BUFSIZE2]; | |
197 | regerror(ret_val, &posix_regexp_begin, msg, ERRMSG_BUFSIZE2); | |
198 | ||
199 | TTCN_Logger::log(TTCN_Logger::DEBUG_ENCDEC, "match_begin regexec result: %d, %s", | |
200 | ret_val,msg); | |
201 | } | |
202 | TTCN_Logger::log(TTCN_Logger::DEBUG_ENCDEC, "match_first result: %d", | |
203 | retval); | |
204 | } | |
205 | return retval; | |
206 | } | |
207 | ||
208 | Limit_Token_List::Limit_Token_List(){ | |
209 | num_of_tokens=0; | |
210 | size_of_list=16; | |
211 | list=(const Token_Match **)Malloc(size_of_list*sizeof(Token_Match *)); | |
212 | last_match=(int *)Malloc(size_of_list*sizeof(int)); | |
213 | last_ret_val=-1; | |
214 | last_pos=NULL; | |
215 | } | |
216 | ||
217 | Limit_Token_List::~Limit_Token_List(){ | |
218 | Free(list); | |
219 | Free(last_match); | |
220 | } | |
221 | ||
222 | void Limit_Token_List::add_token(const Token_Match *token){ | |
223 | if(num_of_tokens==size_of_list){ | |
224 | size_of_list*=2; | |
225 | list=(const Token_Match **)Realloc(list,size_of_list*sizeof(Token_Match *)); | |
226 | last_match=(int *)Realloc(last_match,size_of_list*sizeof(int)); | |
227 | } | |
228 | list[num_of_tokens]=token; | |
229 | last_match[num_of_tokens]=-1; | |
230 | num_of_tokens++; | |
231 | } | |
232 | ||
233 | void Limit_Token_List::remove_tokens(size_t num){ | |
234 | if(num_of_tokens<num) num_of_tokens=0; | |
235 | else num_of_tokens-=num; | |
236 | } | |
237 | ||
238 | int Limit_Token_List::match(TTCN_Buffer& buff, size_t lim){ | |
239 | int ret_val=-1; | |
240 | const char* curr_pos=(const char*)buff.get_read_data(); | |
241 | //TTCN_Logger::log(TTCN_Logger::DEBUG_ENCDEC,"Limit Token begin: %s\n\r",(const char*)buff.get_read_data()); | |
242 | if(last_pos!=NULL){ | |
243 | int diff=curr_pos-last_pos; | |
244 | if(diff){ | |
245 | for(size_t a=0;a<num_of_tokens;a++){ | |
246 | last_match[a]-=diff; | |
247 | } | |
248 | last_ret_val-=diff; | |
249 | } | |
250 | } | |
251 | last_pos=curr_pos; | |
252 | // if(last_ret_val<0){ | |
253 | for(size_t a=0;a<num_of_tokens-lim;a++){ | |
254 | if(last_match[a]<0) last_match[a]=list[a]->match_first(buff); | |
255 | if(last_match[a]>=0){ | |
256 | if(ret_val==-1) ret_val=last_match[a]; | |
257 | else if(last_match[a]<ret_val) ret_val=last_match[a]; | |
258 | } | |
259 | } | |
260 | last_ret_val=ret_val; | |
261 | // } | |
262 | if (TTCN_EncDec::get_error_behavior(TTCN_EncDec::ET_LOG_MATCHING)!= | |
263 | TTCN_EncDec::EB_IGNORE) { | |
264 | TTCN_Logger::log(TTCN_Logger::DEBUG_ENCDEC, | |
265 | "match_list data: %s",(const char*)buff.get_read_data()); | |
266 | TTCN_Logger::log(TTCN_Logger::DEBUG_ENCDEC,"match_list result: %d",ret_val); | |
267 | } | |
268 | return ret_val; | |
269 | } | |
270 | ||
271 | const TTCN_TEXTdescriptor_t INTEGER_text_ = { NULL, NULL, NULL, NULL, | |
272 | NULL, NULL, NULL, { NULL } }; | |
273 | ||
274 | const TTCN_TEXTdescriptor_t BOOLEAN_text_ = { NULL, NULL, NULL, NULL, | |
275 | NULL, NULL, NULL, { NULL } }; | |
276 | ||
277 | const TTCN_TEXTdescriptor_t CHARSTRING_text_ = { NULL, NULL, NULL, NULL, | |
278 | NULL, NULL, NULL, { NULL } }; | |
279 | ||
a38c6d4c | 280 | const TTCN_TEXTdescriptor_t UNIVERSAL_CHARSTRING_text_ = { NULL, NULL, NULL, NULL, |
281 | NULL, NULL, NULL, { NULL } }; | |
282 | ||
970ed795 EL |
283 | const TTCN_TEXTdescriptor_t BITSTRING_text_ = { NULL, NULL, NULL, NULL, |
284 | NULL, NULL, NULL, { NULL } }; | |
285 | ||
286 | const TTCN_TEXTdescriptor_t HEXSTRING_text_ = { NULL, NULL, NULL, NULL, | |
287 | NULL, NULL, NULL, { NULL } }; | |
288 | ||
289 | const TTCN_TEXTdescriptor_t OCTETSTRING_text_ = { NULL, NULL, NULL, NULL, | |
290 | NULL, NULL, NULL, { NULL } }; |