1 #include "ace/Svc_Conf_Lexer.h"
3 #if (ACE_USES_CLASSIC_SVC_CONF == 1)
5 #if defined (ACE_USES_WCHAR)
6 #include "ace/Encoding_Converter.h"
7 #include "ace/Encoding_Converter_Factory.h"
8 #endif /* ACE_USES_WCHAR */
10 #include "ace/Svc_Conf_Tokens.h"
11 #include "ace/Recursive_Thread_Mutex.h"
12 #include "ace/Static_Object_Lock.h"
13 #include "ace/OS_NS_stdio.h"
14 #include "ace/OS_NS_ctype.h"
15 #include "ace/OS_NS_string.h"
16 #include "ace/Guard_T.h"
17 #include "ace/Synch_Traits.h"
18 #include "ace/os_include/os_ctype.h"
20 #if !defined (__GNUG__)
24 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
26 #define ACE_YY_BUF_SIZE 4096
27 #define ACE_MAX_BYTES_PER_CHAR 4
28 #define ACE_YY_CONVERSION_SPACE ACE_YY_BUF_SIZE * ACE_MAX_BYTES_PER_CHAR
30 #if defined (__GNUG__)
31 # define ACE_TEMPORARY_STRING(X,SIZE) \
32 __extension__ char X[SIZE]
34 # define ACE_TEMPORARY_STRING(X,SIZE) \
36 char X ## buf[ACE_YY_BUF_SIZE]; \
37 std::unique_ptr<char> X ## bufp (nullptr); \
38 if (SIZE > ACE_YY_BUF_SIZE) { \
39 X ## bufp.reset (new char[SIZE]); \
40 X = X ## bufp.get (); \
47 // These are states not covered by the tokens in Svc_Conf_Tokens.h
48 #define ACE_NO_STATE -1
51 #if defined (_MSC_VER)
52 // Visual Studio .NET 2005 (VC8) issues warning C4351 for input_ in the
53 // constructor initializer list below. Since we like the warned-of new
54 // behavior (input_ elements will be default-initialized), squash the
56 # pragma warning (push)
57 # pragma warning (disable:4351)
60 struct ace_yy_buffer_state
62 ace_yy_buffer_state ()
69 state_ (ACE_NO_STATE
),
71 #if defined (ACE_USES_WCHAR)
73 #endif /* ACE_USES_WCHAR */
76 #if defined (_MSC_VER)
77 # pragma warning (pop)
80 ~ace_yy_buffer_state ()
82 #if defined (ACE_USES_WCHAR)
84 #endif /* ACE_USES_WCHAR */
87 ACE_ALLOC_HOOK_DECLARE
;
90 char input_
[ACE_YY_CONVERSION_SPACE
];
101 #if defined (ACE_USES_WCHAR)
102 // Code set conversion related
103 ACE_Encoding_Converter
* converter_
;
104 #endif /* ACE_USES_WCHAR */
107 ACE_ALLOC_HOOK_DEFINE(ace_yy_buffer_state
)
109 // ******************************************************************
111 // ******************************************************************
114 ace_yylex (YYSTYPE
*ace_yylval
, void *YYLEX_PARAM
)
116 ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_RECURSIVE_MUTEX
,
118 *ACE_Static_Object_Lock::instance (),
121 return ACE_Svc_Conf_Lexer::yylex (ace_yylval
, ACE_SVC_CONF_PARAM
);
125 ace_yy_delete_buffer (ace_yy_buffer_state
*buffer
)
130 // ******************************************************************
132 // ******************************************************************
135 normalize (size_t length
)
137 return (length
>= ACE_MAX_BYTES_PER_CHAR
?
138 (length
/ ACE_MAX_BYTES_PER_CHAR
) * ACE_MAX_BYTES_PER_CHAR
:
142 // ******************************************************************
143 // Static class methods
144 // ******************************************************************
147 ACE_Svc_Conf_Lexer::yylex (YYSTYPE
* ace_yylval
,
148 ACE_Svc_Conf_Param
* param
)
150 #if defined (ACE_USES_WCHAR)
151 bool look_for_bom
= false;
152 ACE_Encoding_Converter_Factory::Encoding_Hint hint
=
153 ACE_Encoding_Converter_Factory::ACE_NONE
;
154 #endif /* ACE_USES_WCHAR */
155 if (param
->buffer
== 0)
157 #if defined (ACE_USES_WCHAR)
159 #endif /* ACE_USES_WCHAR */
160 ACE_NEW_RETURN (param
->buffer
,
165 int token
= ACE_NO_STATE
;
167 if (param
->buffer
->need_more_
)
169 #if defined (ACE_USES_WCHAR)
170 size_t skip_bytes
= 0;
171 #endif /* ACE_USES_WCHAR */
172 param
->buffer
->need_more_
= false;
175 param
->buffer
->input_
+ param
->buffer
->size_
,
176 normalize (ACE_YY_BUF_SIZE
-
177 param
->buffer
->size_
));
180 param
->buffer
->eof_
= true;
181 #if defined (ACE_USES_WCHAR)
182 skip_bytes
= param
->buffer
->size_
;
183 #endif /* ACE_USES_WCHAR */
187 #if defined (ACE_USES_WCHAR)
190 size_t read_more
= 0;
192 look_for_bom
= false;
193 hint
= locate_bom (param
->buffer
->input_
, amount
, read_more
);
198 param
->buffer
->input_
+ amount
,
200 ACE_OS::memmove (param
->buffer
->input_
,
201 param
->buffer
->input_
+ read_more
,
205 skip_bytes
= param
->buffer
->size_
;
206 #endif /* ACE_USES_WCHAR */
207 param
->buffer
->size_
+= amount
;
210 #if defined (ACE_USES_WCHAR)
211 if (!convert_to_utf8 (param
, skip_bytes
, hint
))
213 ace_yyerror (++param
->yyerrno
,
215 ACE_TEXT ("Unable to convert input stream to UTF-8"));
218 #endif /* ACE_USES_WCHAR */
221 token
= scan (ace_yylval
, param
);
222 } while (token
== ACE_NO_STATE
&& param
->buffer
->need_more_
);
228 ACE_Svc_Conf_Lexer::input (ACE_Svc_Conf_Param
* param
,
229 char* buf
, size_t max_size
)
235 case ACE_Svc_Conf_Param::SVC_CONF_FILE
:
237 while ((result
= ACE_OS::fread (buf
, 1,
238 max_size
, param
->source
.file
)) == 0 &&
239 ferror (param
->source
.file
))
244 ACE_OS::clearerr (param
->source
.file
);
248 #ifndef ACE_LACKS_STDERR
249 ACE_OS::fprintf (stderr
, "ERROR: input in scanner failed\n");
255 case ACE_Svc_Conf_Param::SVC_CONF_DIRECTIVE
:
256 result
= ACE_OS::strlen (param
->source
.directive
+
257 param
->buffer
->start_
) * sizeof (ACE_TCHAR
);
260 // Make sure that the amount we are going to copy
261 // fits in the buffer
262 if (result
> max_size
)
267 param
->source
.directive
+ param
->buffer
->start_
,
269 param
->buffer
->start_
+= (result
/ sizeof (ACE_TCHAR
));
273 ace_yyerror (++param
->yyerrno
,
275 ACE_TEXT ("Invalid Service Configurator type in ")
276 ACE_TEXT ("ACE_Svc_Conf_Lexer::input"));
283 ACE_Svc_Conf_Lexer::scan (YYSTYPE
* ace_yylval
,
284 ACE_Svc_Conf_Param
* param
)
287 ace_yy_buffer_state
* buffer
= param
->buffer
;
289 // If we are not currently in any state, skip over whitespace
290 if (buffer
->state_
== ACE_NO_STATE
)
292 while (buffer
->index_
< buffer
->size_
&&
293 isspace (buffer
->input_
[buffer
->index_
]))
295 // Make sure that we count all of the new lines
296 if (buffer
->input_
[buffer
->index_
] == '\n')
305 size_t last
= buffer
->size_
+ (buffer
->eof_
? 1 : 0);
306 for (current
= buffer
->index_
; current
< last
; current
++)
308 static const char* separators
= " \t\r\n:*(){}";
309 char c
= (buffer
->eof_
&& current
== buffer
->size_
?
310 '\n' : buffer
->input_
[current
]);
311 switch (buffer
->state_
)
316 buffer
->state_
= ACE_NO_STATE
;
317 buffer
->index_
= current
+ 1;
322 if (!(c
>= ' ' && c
<= '~'))
324 // The character at currrent is definitely not part of
325 // the string so we need to move current back one.
328 // Get the starting point of our string (skipping the quote)
329 char* source
= buffer
->input_
+ buffer
->index_
+ 1;
331 // Now, we need to move back in the string until we find the
332 // same character that started the string
333 bool string_end_found
= false;
334 if (current
> buffer
->index_
)
336 for (size_t i
= current
- buffer
->index_
; i
-- != 0; )
338 if (source
[i
] == buffer
->string_start_
)
340 current
= buffer
->index_
+ i
+ 1;
341 string_end_found
= true;
347 if (!string_end_found
)
349 ace_yyerror (++param
->yyerrno
,
351 ACE_TEXT ("Unable to find the end of the string"));
355 size_t amount
= (current
- buffer
->index_
) - 1;
356 #if defined (ACE_USES_WCHAR)
357 ACE_TCHAR target
[ACE_YY_CONVERSION_SPACE
] = ACE_TEXT ("");
359 if (!convert_from_utf8 (buffer
->converter_
,
363 ACE_YY_CONVERSION_SPACE
,
366 ace_yyerror (++param
->yyerrno
,
368 ACE_TEXT ("Unable to convert string from UTF-8"));
373 char* target
= source
;
374 #endif /* ACE_USES_WCHAR */
375 ace_yylval
->ident_
= param
->obstack
.copy (target
, amount
);
376 buffer
->state_
= ACE_NO_STATE
;
377 buffer
->index_
= current
+ 1;
382 if (c
== '"' || c
== '\'')
384 buffer
->string_start_
= c
;
385 buffer
->state_
= ACE_STRING
;
389 buffer
->state_
= ACE_COMMENT
;
391 else if (ACE_OS::strchr (separators
, c
) != 0)
398 if (current
== buffer
->index_
+ 1)
400 int const lower
= ACE_OS::ace_tolower (
401 buffer
->input_
[current
- 1]);
403 (buffer
->input_
[current
- 1] == '%' ||
404 (lower
>= 'a' && lower
<= 'z')))
406 // This is considered a path, so we need to
407 // skip over the ':' and go around the loop
413 if (current
== buffer
->index_
)
415 buffer
->index_
= current
+ 1;
418 // This is an empty line.
419 // Let's look for something else.
428 // String from buffer->index_ to current (inclusive)
429 size_t size
= (current
- buffer
->index_
) + 1;
430 ACE_TEMPORARY_STRING (str
, size
);
431 ACE_OS::strncpy (str
, buffer
->input_
+ buffer
->index_
,
433 str
[size
- 1] = '\0';
436 if (ACE_OS::strcmp (str
, "dynamic") == 0)
438 buffer
->index_
= current
;
441 else if (ACE_OS::strcmp (str
, "static") == 0)
443 buffer
->index_
= current
;
446 else if (ACE_OS::strcmp (str
, "suspend") == 0)
448 buffer
->index_
= current
;
451 else if (ACE_OS::strcmp (str
, "resume") == 0)
453 buffer
->index_
= current
;
456 else if (ACE_OS::strcmp (str
, "remove") == 0)
458 buffer
->index_
= current
;
461 else if (ACE_OS::strcmp (str
, "stream") == 0)
463 buffer
->index_
= current
;
466 else if (ACE_OS::strcmp (str
, "Module") == 0)
468 buffer
->index_
= current
;
471 else if (ACE_OS::strcmp (str
, "Service_Object") == 0)
473 buffer
->index_
= current
;
474 return ACE_SVC_OBJ_T
;
476 else if (ACE_OS::strcmp (str
, "STREAM") == 0)
478 buffer
->index_
= current
;
481 else if (ACE_OS::strcmp (str
, "active") == 0)
483 buffer
->index_
= current
;
486 else if (ACE_OS::strcmp (str
, "inactive") == 0)
488 buffer
->index_
= current
;
493 // Get the string and save it in ace_yylval
494 int token
= ACE_IDENT
;
495 size_t amount
= size
- 1;
496 #if defined (ACE_USES_WCHAR)
497 ACE_TCHAR target
[ACE_YY_CONVERSION_SPACE
] = ACE_TEXT ("");
499 if (!convert_from_utf8 (buffer
->converter_
,
503 ACE_YY_CONVERSION_SPACE
,
506 ace_yyerror (++param
->yyerrno
,
508 ACE_TEXT ("Unable to convert ")
509 ACE_TEXT ("identifier from UTF-8"));
515 #endif /* ACE_USES_WCHAR */
516 ace_yylval
->ident_
= param
->obstack
.copy (target
, amount
);
518 // Determine the difference between pathname and ident
519 if (ACE_OS::ace_isdigit (ace_yylval
->ident_
[0]))
521 token
= ACE_PATHNAME
;
525 static const ACE_TCHAR
* path_parts
=
526 ACE_TEXT ("/\\:%.~-");
527 for (const ACE_TCHAR
* p
= path_parts
; *p
!= '\0'; p
++)
529 if (ACE_OS::strchr (ace_yylval
->ident_
, *p
) != 0)
531 token
= ACE_PATHNAME
;
537 buffer
->state_
= ACE_NO_STATE
;
538 buffer
->index_
= current
;
544 ace_yyerror (++param
->yyerrno
,
546 ACE_TEXT ("Unexpected state in ACE_Svc_Conf_Lexer::scan"));
551 // We need more from the input source so, we will move the remainder of
552 // the buffer to the front and signal that we need more
555 buffer
->need_more_
= true;
556 if (buffer
->state_
== ACE_COMMENT
)
563 buffer
->size_
= current
- buffer
->index_
;
564 if (buffer
->size_
!= 0 && buffer
->index_
!= 0)
565 ACE_OS::memmove (buffer
->input_
,
566 buffer
->input_
+ buffer
->index_
, buffer
->size_
);
568 buffer
->state_
= ACE_NO_STATE
;
574 #if defined (ACE_USES_WCHAR)
577 ACE_Svc_Conf_Lexer::convert_to_utf8 (
578 ACE_Svc_Conf_Param
* param
,
580 ACE_Encoding_Converter_Factory::Encoding_Hint hint
)
583 if (param
->buffer
->converter_
== 0)
585 param
->buffer
->converter_
=
586 ACE_Encoding_Converter_Factory::create (
587 reinterpret_cast<ACE_Byte
*> (param
->buffer
->input_
+ skip_bytes
),
588 param
->buffer
->size_
- skip_bytes
,
592 if (param
->buffer
->converter_
!= 0)
594 char target
[ACE_YY_CONVERSION_SPACE
] = "";
595 if (param
->buffer
->converter_
->to_utf8 (
596 param
->buffer
->input_
+ skip_bytes
,
597 param
->buffer
->size_
- skip_bytes
,
598 reinterpret_cast<ACE_Byte
*> (target
),
599 ACE_YY_CONVERSION_SPACE
) == ACE_Encoding_Converter::CONVERSION_OK
)
601 ACE_OS::strcpy (param
->buffer
->input_
+ skip_bytes
, target
);
602 param
->buffer
->size_
= ACE_OS::strlen (target
) + skip_bytes
;
611 ACE_Svc_Conf_Lexer::convert_from_utf8 (ACE_Encoding_Converter
* converter
,
620 if (converter
->from_utf8 (
621 reinterpret_cast <const ACE_Byte
*> (source
),
624 target_size
) != ACE_Encoding_Converter::CONVERSION_OK
)
631 ACE_OS::strncpy (target
, ACE_TEXT_CHAR_TO_TCHAR (source
), source_size
);
632 target
[source_size
] = 0;
635 length
= ACE_OS::strlen (target
);
639 ACE_Encoding_Converter_Factory::Encoding_Hint
640 ACE_Svc_Conf_Lexer::locate_bom (char* source
,
647 ACE_Encoding_Converter_Factory::Encoding_Hint hint_
;
649 static const bom boms
[] = {
650 { 4, "\x00\x00\xfe\xff", ACE_Encoding_Converter_Factory::ACE_UTF_32BE
},
651 { 4, "\xff\xfe\x00\x00", ACE_Encoding_Converter_Factory::ACE_UTF_32LE
},
652 { 2, "\xfe\xff", ACE_Encoding_Converter_Factory::ACE_UTF_16BE
},
653 { 2, "\xff\xfe", ACE_Encoding_Converter_Factory::ACE_UTF_16LE
},
654 { 3, "\xef\xbb\xbf", ACE_Encoding_Converter_Factory::ACE_UTF_8
},
657 for (size_t i
= 0; i
< sizeof (boms
) / sizeof (bom
); i
++)
659 if (source_size
>= boms
[i
].length_
)
661 if (ACE_OS::memcmp (source
,
662 boms
[i
].data_
, boms
[i
].length_
) == 0)
664 bytes_used
= boms
[i
].length_
;
665 return boms
[i
].hint_
;
672 return ACE_Encoding_Converter_Factory::ACE_NONE
;
675 #endif /* ACE_USES_WCHAR */
677 ACE_END_VERSIONED_NAMESPACE_DECL
678 #endif /* ACE_USES_CLASSIC_SVC_CONF = 1 */