1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2014 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 ///////////////////////////////////////////////////////////////////////////////
10 #include "common/pattern.hh"
11 #include "common/pattern_p.hh"
13 void TextAST::init_TextAST()
22 coding_params
.leading_zero
=false;
23 coding_params
.repeatable
=false;
24 coding_params
.min_length
=-1;
25 coding_params
.max_length
=-1;
26 coding_params
.convert
=0;
28 decoding_params
.leading_zero
=false;
29 decoding_params
.repeatable
=false;
30 decoding_params
.min_length
=-1;
31 decoding_params
.max_length
=-1;
32 decoding_params
.convert
=0;
33 decoding_params
.just
=1;
38 TextAST::TextAST(const TextAST
*other_val
)
43 //other_val->print_TextAST();
44 copy_textAST_matching_values(&begin_val
,other_val
->begin_val
);
45 copy_textAST_matching_values(&end_val
,other_val
->end_val
);
46 copy_textAST_matching_values(&separator_val
,other_val
->separator_val
);
48 nof_field_params
=other_val
->nof_field_params
;
49 if(nof_field_params
) field_params
=
50 (textAST_enum_def
**)Malloc(nof_field_params
*sizeof(textAST_enum_def
*));
51 for(int a
=0;a
<nof_field_params
;a
++){
52 if(other_val
->field_params
[a
]){
53 field_params
[a
]=(textAST_enum_def
*)Malloc(sizeof(textAST_enum_def
));
54 field_params
[a
]->name
=
55 new Common::Identifier(*(other_val
->field_params
[a
]->name
));
56 textAST_matching_values
*b
=&(field_params
[a
]->value
);
57 copy_textAST_matching_values(&b
,&other_val
->field_params
[a
]->value
);
58 } else field_params
[a
]=NULL
;
62 copy_textAST_matching_values(&true_params
,other_val
->true_params
);
63 copy_textAST_matching_values(&false_params
,other_val
->false_params
);
65 coding_params
.leading_zero
=other_val
->coding_params
.leading_zero
;
66 coding_params
.repeatable
=other_val
->coding_params
.repeatable
;
67 coding_params
.min_length
=other_val
->coding_params
.min_length
;
68 coding_params
.max_length
=other_val
->coding_params
.max_length
;
69 coding_params
.convert
=other_val
->coding_params
.convert
;
70 coding_params
.just
=other_val
->coding_params
.just
;
71 decoding_params
.leading_zero
=other_val
->decoding_params
.leading_zero
;
72 decoding_params
.repeatable
=other_val
->decoding_params
.repeatable
;
73 decoding_params
.min_length
=other_val
->decoding_params
.min_length
;
74 decoding_params
.max_length
=other_val
->decoding_params
.max_length
;
75 decoding_params
.convert
=other_val
->decoding_params
.convert
;
76 decoding_params
.just
=other_val
->decoding_params
.just
;
78 if(other_val
->decode_token
)
79 decode_token
=mcopystr(other_val
->decode_token
);
80 case_sensitive
=other_val
->case_sensitive
;
87 Free(begin_val
->encode_token
);
88 Free(begin_val
->decode_token
);
92 Free(end_val
->encode_token
);
93 Free(end_val
->decode_token
);
97 Free(separator_val
->encode_token
);
98 Free(separator_val
->decode_token
);
102 for(int a
=0;a
<nof_field_params
;a
++){
104 delete field_params
[a
]->name
;
105 Free(field_params
[a
]->value
.encode_token
);
106 Free(field_params
[a
]->value
.decode_token
);
108 Free(field_params
[a
]);
113 Free(true_params
->encode_token
);
114 Free(true_params
->decode_token
);
118 Free(false_params
->encode_token
);
119 Free(false_params
->decode_token
);
125 void TextAST::print_TextAST() const
127 printf("\n\rBegin:");
129 printf("\n\r Encode token:");
130 if(begin_val
->encode_token
) printf(" %s\n\r",begin_val
->encode_token
);
131 else printf(" NULL\n\r");
132 printf(" Decode token:");
133 if(begin_val
->decode_token
) printf(" %s\n\r",begin_val
->decode_token
);
134 else printf(" NULL\n\r");
135 if(begin_val
->case_sensitive
) printf(" case_sensitive\n\r");
136 else printf(" case_insensitive\n\r");
138 else printf("NULL\n\r");
141 printf("\n\r Encode token:");
142 if(end_val
->encode_token
) printf(" %s\n\r",end_val
->encode_token
);
143 else printf(" NULL\n\r");
144 printf(" Decode token:");
145 if(end_val
->decode_token
) printf(" %s\n\r",end_val
->decode_token
);
146 else printf(" NULL\n\r");
147 if(end_val
->case_sensitive
) printf(" case_sensitive\n\r");
148 else printf(" case_insensitive\n\r");
150 else printf("NULL\n\r");
151 printf("Separator:");
153 printf("\n\r Encode token:");
154 if(separator_val
->encode_token
) printf(" %s\n\r",separator_val
->encode_token
);
155 else printf(" NULL\n\r");
156 printf(" Decode token:");
157 if(separator_val
->decode_token
) printf(" %s\n\r",separator_val
->decode_token
);
158 else printf(" NULL\n\r");
159 if(separator_val
->case_sensitive
) printf(" case_sensitive\n\r");
160 else printf(" case_insensitive\n\r");
162 else printf("NULL\n\r");
163 printf("Select token:");
164 if(decode_token
) printf("%s",decode_token
);
165 if(case_sensitive
) printf(" case_sensitive\n\r");
166 else printf(" case_insensitive\n\r");
169 printf("\n\r Encode token:");
170 if(true_params
->encode_token
) printf(" %s\n\r",true_params
->encode_token
);
171 else printf(" NULL\n\r");
172 printf(" Decode token:");
173 if(true_params
->decode_token
) printf(" %s\n\r",true_params
->decode_token
);
174 else printf(" NULL\n\r");
175 if(true_params
->case_sensitive
) printf(" case_sensitive\n\r");
176 else printf(" case_insensitive\n\r");
178 else printf("NULL\n\r");
181 printf("\n\r Encode token:");
182 if(false_params
->encode_token
) printf(" %s\n\r",false_params
->encode_token
);
183 else printf(" NULL\n\r");
184 printf(" Decode token:");
185 if(false_params
->decode_token
) printf(" %s\n\r",false_params
->decode_token
);
186 else printf(" NULL\n\r");
187 if(false_params
->case_sensitive
) printf(" case_sensitive\n\r");
188 else printf(" case_insensitive\n\r");
190 else printf("NULL\n\r");
191 printf("Number of fields:%i\n\r",nof_field_params
);
192 for(int a
=0;a
<nof_field_params
;a
++){
193 printf("Field %i:\n\r",a
);
195 printf(" Name: %s\n\r",field_params
[a
]->name
->get_name().c_str());
196 printf(" Encode token:");
197 if(field_params
[a
]->value
.encode_token
) printf(" %s\n\r",field_params
[a
]->value
.encode_token
);
198 else printf(" NULL\n\r");
199 printf(" Decode token:");
200 if(field_params
[a
]->value
.decode_token
) printf(" %s\n\r",field_params
[a
]->value
.decode_token
);
201 else printf(" NULL\n\r");
202 if(field_params
[a
]->value
.case_sensitive
) printf(" case_sensitive\n\r");
203 else printf(" case_insensitive\n\r");
204 } else printf(" NULL\n\r");
206 printf("Coding params:\n\r Leading 0:");
207 if(coding_params
.leading_zero
) printf(" true\n\r");
208 else printf(" false\n\r");
209 printf(" Length: %i - %i\n\r",coding_params
.min_length
,coding_params
.max_length
);
210 printf(" Convert: %i\n\r Just:%i\n\r",coding_params
.convert
,coding_params
.just
);
212 printf("Decoding params:\n\r Leading 0:");
213 if(decoding_params
.leading_zero
) printf(" true\n\r");
214 else printf(" false\n\r");
215 printf(" Length: %i - %i\n\r",decoding_params
.min_length
,decoding_params
.max_length
);
216 printf(" Convert: %i\n\r Just:%i\n\r",decoding_params
.convert
,decoding_params
.just
);
219 int TextAST::get_field_param_index(const Common::Identifier
*name
)
221 for(int a
=0;a
<nof_field_params
;a
++){
222 if(*field_params
[a
]->name
==*name
) return a
;
224 field_params
=(textAST_enum_def
**)Realloc(field_params
,(nof_field_params
+1)*sizeof(textAST_enum_def
*));
225 field_params
[nof_field_params
]=(textAST_enum_def
*)Malloc(sizeof(textAST_enum_def
));
226 field_params
[nof_field_params
]->name
= new Common::Identifier(*name
);
227 field_params
[nof_field_params
]->value
.encode_token
=NULL
;
228 field_params
[nof_field_params
]->value
.decode_token
=NULL
;
229 field_params
[nof_field_params
]->value
.case_sensitive
=true;
231 return nof_field_params
-1;
234 void copy_textAST_matching_values(textAST_matching_values
**to
,
235 const textAST_matching_values
*from
)
237 if(from
==NULL
) return;
239 *to
=(textAST_matching_values
*)Malloc(sizeof(textAST_matching_values
));
240 if(from
->encode_token
) (*to
)->encode_token
=mcopystr(from
->encode_token
);
241 else (*to
)->encode_token
=NULL
;
242 if(from
->decode_token
&& !from
->generated_decode_token
)
243 (*to
)->decode_token
=mcopystr(from
->decode_token
);
244 else (*to
)->decode_token
=NULL
;
245 (*to
)->case_sensitive
=from
->case_sensitive
;
246 (*to
)->generated_decode_token
=false;
249 char *process_decode_token(const char *decode_token
,
250 const Common::Location
& loc
)
252 enum { INITIAL
, BS
, BS_N
, BS_Q
} state
= INITIAL
;
253 // points to the last backslash found
255 char *ret_val
= memptystr();
256 for (size_t i
= 0; decode_token
[i
] != '\0'; i
++) {
259 switch (decode_token
[i
]) {
265 // {reference}: find the matching bracket and skip the entire reference
266 for (size_t j
= i
+ 1; ; j
++) {
267 if (decode_token
[j
] == '\0') {
268 loc
.error("Invalid reference `%s' in matching pattern",
272 } else if (decode_token
[j
] == '}') {
273 loc
.error("Reference `%s' is not allowed in matching pattern",
274 string(j
+ 1 - i
, decode_token
+ i
).c_str());
282 // replace '' -> ' and "" -> "
283 ret_val
= mputc(ret_val
, decode_token
[i
]);
284 if (decode_token
[i
+ 1] == decode_token
[i
]) i
++;
287 ret_val
= mputc(ret_val
, decode_token
[i
]);
291 switch (decode_token
[i
]) {
300 // replace \' -> ' and \" -> "
301 ret_val
= mputc(ret_val
, decode_token
[i
]);
305 // keep other escape sequences
306 ret_val
= mputc(ret_val
, '\\');
307 ret_val
= mputc(ret_val
, decode_token
[i
]);
312 switch (decode_token
[i
]) {
319 // ignore whitespace following \N
322 // \N{reference}: find the matching bracket and skip the entire
324 for (size_t j
= i
+ 1; ; j
++) {
325 if (decode_token
[j
] == '\0') {
326 loc
.error("Invalid character set reference `%s' in matching "
327 "pattern", decode_token
+ bs_idx
);
330 } else if (decode_token
[j
] == '}') {
331 loc
.error("Character set reference `%s' is not allowed in matching "
332 "pattern", string(j
+ 1 - bs_idx
, decode_token
+ bs_idx
).c_str());
340 loc
.error("Invalid character set reference `%s' in matching pattern",
341 string(i
+ 1 - bs_idx
, decode_token
+ bs_idx
).c_str());
346 switch (decode_token
[i
]) {
353 // ignore whitespace following \q
356 // copy the rest of the quadruple literally
357 ret_val
= mputstr(ret_val
, "\\q{");
361 loc
.error("Invalid quadruple notation `%s' in matching pattern",
362 string(i
+ 1 - bs_idx
, decode_token
+ bs_idx
).c_str());
367 // final check of state
372 loc
.error("Invalid trailing backslash in matching pattern");
375 loc
.error("Invalid character set reference `%s' in matching pattern",
376 decode_token
+ bs_idx
);
379 loc
.error("Invalid quadruple notation `%s' in matching pattern",
380 decode_token
+ bs_idx
);
385 extern bool has_meta(); // in pattern_la.l
387 extern int pattern_yylex();
388 extern void init_pattern_yylex(YYSTYPE
*p
);
389 struct yy_buffer_state
;
390 extern yy_buffer_state
* pattern_yy_scan_string(const char*);
391 extern int pattern_yylex_destroy();
393 char *make_posix_str_code(const char *pat
, bool cs
)
395 if (pat
== NULL
|| pat
[0] == '\0') return mcopystr("I");
398 ret_val
= mcopystr(cs
? "I" : "N"); // Case sensitive? _I_gen / _N_em
400 // Run the pattern lexer over the pattern to check for meta-characters.
401 // TTCN_pattern_to_regexp() would be overkill.
402 yy_buffer_state
*flex_buffer
= pattern_yy_scan_string(pat
);
403 if (flex_buffer
== NULL
) {} //a fatal error was already generated
406 init_pattern_yylex(&yylval
);
407 while (pattern_yylex()) {} // 0 means end-of-string
408 pattern_yylex_destroy();
411 // If the matching is case sensitive and there are no meta-characters,
412 // matching for fixed strings can be done without regular expressions.
413 const bool maybe_fixed
= cs
&& !has_meta();
415 char *mod_token
= mprintf("(%s)*", pat
);
416 // disable all warnings and "not supported" messages while translating the
417 // pattern to POSIX regexp again (these messages were already reported
418 // during semantic analysis)
419 unsigned orig_verb_level
= verb_level
;
420 verb_level
&= ~(1|2);
421 char *posix_str
= TTCN_pattern_to_regexp(mod_token
);
422 verb_level
= orig_verb_level
;
424 if (posix_str
== NULL
) FATAL_ERROR("make_posix_str_code()");
426 size_t len
= mstrlen(posix_str
), skip
= 0;
427 if (maybe_fixed
) { // maybe we can do fixed strings
428 *ret_val
= 'F'; // "fixed"
430 // posix_str contains: ^(pat).*$ but all we need is pat
431 ret_val
= mputstrn(ret_val
, posix_str
+ 2, len
- 6);
433 else { // no fixed-string optimization possible
434 // TEXT decoder optimization
436 if (!memcmp(posix_str
+ (len
- 3), ".*$", 3)) {
437 // The POSIX RE is set to match a bunch of characters before the end.
438 // This happens if the TTCN pattern wanted to match anywhere, not just
439 // at the end (TTCN patterns are anchored at the beginning and end).
440 // Instead of looking for (0 or more) characters and ignoring them,
441 // just don't look for them at all. RE are not anchored by default.
442 posix_str
= mtruncstr(posix_str
, len
-= 3);
445 if (len
> 3) { // len might have changed while truncating, above
446 // Un-anchor the cheap way, at the beginning.
447 skip
= memcmp(posix_str
, "^.*", 3) ? 0 : 3;
451 ret_val
= mputstr(ret_val
, posix_str
+ skip
);
459 char *convert_charstring_to_pattern(const char *str
)
461 char *ret_val
= memptystr();
462 for (size_t i
= 0; str
[i
]; i
++) {
476 // special characters of TTCN-3 patterns; escape with a backslash
477 ret_val
= mputc(ret_val
, '\\');
480 ret_val
= mputc(ret_val
, str
[i
]);
486 void init_textAST_matching_values(textAST_matching_values
*val
){
487 val
->encode_token
=NULL
;
488 val
->decode_token
=NULL
;
489 val
->case_sensitive
=true;
490 val
->generated_decode_token
=false;
This page took 0.04141 seconds and 5 git commands to generate.