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__)
21 # include "ace/Auto_Ptr.h"
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 ACE_Auto_Ptr<char> X ## bufp (0); \
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) && (_MSC_VER >= 1400)
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 (void)
69 state_ (ACE_NO_STATE
),
71 #if defined (ACE_USES_WCHAR)
73 #endif /* ACE_USES_WCHAR */
76 #if defined (_MSC_VER) && (_MSC_VER >= 1400)
77 # pragma warning (pop)
80 ~ace_yy_buffer_state (void)
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
);
126 ace_yy_delete_buffer (ace_yy_buffer_state
*buffer
)
131 // ******************************************************************
133 // ******************************************************************
136 normalize (size_t length
)
138 return (length
>= ACE_MAX_BYTES_PER_CHAR
?
139 (length
/ ACE_MAX_BYTES_PER_CHAR
) * ACE_MAX_BYTES_PER_CHAR
:
143 // ******************************************************************
144 // Static class methods
145 // ******************************************************************
148 ACE_Svc_Conf_Lexer::yylex (YYSTYPE
* ace_yylval
,
149 ACE_Svc_Conf_Param
* param
)
151 #if defined (ACE_USES_WCHAR)
152 bool look_for_bom
= false;
153 ACE_Encoding_Converter_Factory::Encoding_Hint hint
=
154 ACE_Encoding_Converter_Factory::ACE_NONE
;
155 #endif /* ACE_USES_WCHAR */
156 if (param
->buffer
== 0)
158 #if defined (ACE_USES_WCHAR)
160 #endif /* ACE_USES_WCHAR */
161 ACE_NEW_RETURN (param
->buffer
,
166 int token
= ACE_NO_STATE
;
168 if (param
->buffer
->need_more_
)
170 #if defined (ACE_USES_WCHAR)
171 size_t skip_bytes
= 0;
172 #endif /* ACE_USES_WCHAR */
173 param
->buffer
->need_more_
= false;
176 param
->buffer
->input_
+ param
->buffer
->size_
,
177 normalize (ACE_YY_BUF_SIZE
-
178 param
->buffer
->size_
));
181 param
->buffer
->eof_
= true;
182 #if defined (ACE_USES_WCHAR)
183 skip_bytes
= param
->buffer
->size_
;
184 #endif /* ACE_USES_WCHAR */
188 #if defined (ACE_USES_WCHAR)
191 size_t read_more
= 0;
193 look_for_bom
= false;
194 hint
= locate_bom (param
->buffer
->input_
, amount
, read_more
);
199 param
->buffer
->input_
+ amount
,
201 ACE_OS::memmove (param
->buffer
->input_
,
202 param
->buffer
->input_
+ read_more
,
206 skip_bytes
= param
->buffer
->size_
;
207 #endif /* ACE_USES_WCHAR */
208 param
->buffer
->size_
+= amount
;
211 #if defined (ACE_USES_WCHAR)
212 if (!convert_to_utf8 (param
, skip_bytes
, hint
))
214 ace_yyerror (++param
->yyerrno
,
216 ACE_TEXT ("Unable to convert input stream to UTF-8"));
219 #endif /* ACE_USES_WCHAR */
222 token
= scan (ace_yylval
, param
);
223 } while (token
== ACE_NO_STATE
&& param
->buffer
->need_more_
);
229 ACE_Svc_Conf_Lexer::input (ACE_Svc_Conf_Param
* param
,
230 char* buf
, size_t max_size
)
236 case ACE_Svc_Conf_Param::SVC_CONF_FILE
:
238 while ((result
= ACE_OS::fread (buf
, 1,
239 max_size
, param
->source
.file
)) == 0 &&
240 ferror (param
->source
.file
))
245 ACE_OS::clearerr (param
->source
.file
);
249 #ifndef ACE_LACKS_STDERR
250 ACE_OS::fprintf (stderr
, "ERROR: input in scanner failed\n");
256 case ACE_Svc_Conf_Param::SVC_CONF_DIRECTIVE
:
257 result
= ACE_OS::strlen (param
->source
.directive
+
258 param
->buffer
->start_
) * sizeof (ACE_TCHAR
);
261 // Make sure that the amount we are going to copy
262 // fits in the buffer
263 if (result
> max_size
)
268 param
->source
.directive
+ param
->buffer
->start_
,
270 param
->buffer
->start_
+= (result
/ sizeof (ACE_TCHAR
));
274 ace_yyerror (++param
->yyerrno
,
276 ACE_TEXT ("Invalid Service Configurator type in ")
277 ACE_TEXT ("ACE_Svc_Conf_Lexer::input"));
284 ACE_Svc_Conf_Lexer::scan (YYSTYPE
* ace_yylval
,
285 ACE_Svc_Conf_Param
* param
)
288 ace_yy_buffer_state
* buffer
= param
->buffer
;
290 // If we are not currently in any state, skip over whitespace
291 if (buffer
->state_
== ACE_NO_STATE
)
293 while (buffer
->index_
< buffer
->size_
&&
294 isspace (buffer
->input_
[buffer
->index_
]))
296 // Make sure that we count all of the new lines
297 if (buffer
->input_
[buffer
->index_
] == '\n')
306 size_t last
= buffer
->size_
+ (buffer
->eof_
? 1 : 0);
307 for (current
= buffer
->index_
; current
< last
; current
++)
309 static const char* separators
= " \t\r\n:*(){}";
310 char c
= (buffer
->eof_
&& current
== buffer
->size_
?
311 '\n' : buffer
->input_
[current
]);
312 switch (buffer
->state_
)
317 buffer
->state_
= ACE_NO_STATE
;
318 buffer
->index_
= current
+ 1;
323 if (!(c
>= ' ' && c
<= '~'))
325 // The character at currrent is definitely not part of
326 // the string so we need to move current back one.
329 // Get the starting point of our string (skipping the quote)
330 char* source
= buffer
->input_
+ buffer
->index_
+ 1;
332 // Now, we need to move back in the string until we find the
333 // same character that started the string
334 bool string_end_found
= false;
335 if (current
> buffer
->index_
)
337 for (size_t i
= current
- buffer
->index_
; i
-- != 0; )
339 if (source
[i
] == buffer
->string_start_
)
341 current
= buffer
->index_
+ i
+ 1;
342 string_end_found
= true;
348 if (!string_end_found
)
350 ace_yyerror (++param
->yyerrno
,
352 ACE_TEXT ("Unable to find the end of the string"));
356 size_t amount
= (current
- buffer
->index_
) - 1;
357 #if defined (ACE_USES_WCHAR)
358 ACE_TCHAR target
[ACE_YY_CONVERSION_SPACE
] = ACE_TEXT ("");
360 if (!convert_from_utf8 (buffer
->converter_
,
364 ACE_YY_CONVERSION_SPACE
,
367 ace_yyerror (++param
->yyerrno
,
369 ACE_TEXT ("Unable to convert string from UTF-8"));
374 char* target
= source
;
375 #endif /* ACE_USES_WCHAR */
376 ace_yylval
->ident_
= param
->obstack
.copy (target
, amount
);
377 buffer
->state_
= ACE_NO_STATE
;
378 buffer
->index_
= current
+ 1;
383 if (c
== '"' || c
== '\'')
385 buffer
->string_start_
= c
;
386 buffer
->state_
= ACE_STRING
;
390 buffer
->state_
= ACE_COMMENT
;
392 else if (ACE_OS::strchr (separators
, c
) != 0)
399 if (current
== buffer
->index_
+ 1)
401 int const lower
= ACE_OS::ace_tolower (
402 buffer
->input_
[current
- 1]);
404 (buffer
->input_
[current
- 1] == '%' ||
405 (lower
>= 'a' && lower
<= 'z')))
407 // This is considered a path, so we need to
408 // skip over the ':' and go around the loop
414 if (current
== buffer
->index_
)
416 buffer
->index_
= current
+ 1;
419 // This is an empty line.
420 // Let's look for something else.
429 // String from buffer->index_ to current (inclusive)
430 size_t size
= (current
- buffer
->index_
) + 1;
431 ACE_TEMPORARY_STRING (str
, size
);
432 ACE_OS::strncpy (str
, buffer
->input_
+ buffer
->index_
,
434 str
[size
- 1] = '\0';
437 if (ACE_OS::strcmp (str
, "dynamic") == 0)
439 buffer
->index_
= current
;
442 else if (ACE_OS::strcmp (str
, "static") == 0)
444 buffer
->index_
= current
;
447 else if (ACE_OS::strcmp (str
, "suspend") == 0)
449 buffer
->index_
= current
;
452 else if (ACE_OS::strcmp (str
, "resume") == 0)
454 buffer
->index_
= current
;
457 else if (ACE_OS::strcmp (str
, "remove") == 0)
459 buffer
->index_
= current
;
462 else if (ACE_OS::strcmp (str
, "stream") == 0)
464 buffer
->index_
= current
;
467 else if (ACE_OS::strcmp (str
, "Module") == 0)
469 buffer
->index_
= current
;
472 else if (ACE_OS::strcmp (str
, "Service_Object") == 0)
474 buffer
->index_
= current
;
475 return ACE_SVC_OBJ_T
;
477 else if (ACE_OS::strcmp (str
, "STREAM") == 0)
479 buffer
->index_
= current
;
482 else if (ACE_OS::strcmp (str
, "active") == 0)
484 buffer
->index_
= current
;
487 else if (ACE_OS::strcmp (str
, "inactive") == 0)
489 buffer
->index_
= current
;
494 // Get the string and save it in ace_yylval
495 int token
= ACE_IDENT
;
496 size_t amount
= size
- 1;
497 #if defined (ACE_USES_WCHAR)
498 ACE_TCHAR target
[ACE_YY_CONVERSION_SPACE
] = ACE_TEXT ("");
500 if (!convert_from_utf8 (buffer
->converter_
,
504 ACE_YY_CONVERSION_SPACE
,
507 ace_yyerror (++param
->yyerrno
,
509 ACE_TEXT ("Unable to convert ")
510 ACE_TEXT ("identifier from UTF-8"));
516 #endif /* ACE_USES_WCHAR */
517 ace_yylval
->ident_
= param
->obstack
.copy (target
, amount
);
519 // Determine the difference between pathname and ident
520 if (ACE_OS::ace_isdigit (ace_yylval
->ident_
[0]))
522 token
= ACE_PATHNAME
;
526 static const ACE_TCHAR
* path_parts
=
527 ACE_TEXT ("/\\:%.~-");
528 for (const ACE_TCHAR
* p
= path_parts
; *p
!= '\0'; p
++)
530 if (ACE_OS::strchr (ace_yylval
->ident_
, *p
) != 0)
532 token
= ACE_PATHNAME
;
538 buffer
->state_
= ACE_NO_STATE
;
539 buffer
->index_
= current
;
545 ace_yyerror (++param
->yyerrno
,
547 ACE_TEXT ("Unexpected state in ACE_Svc_Conf_Lexer::scan"));
552 // We need more from the input source so, we will move the remainder of
553 // the buffer to the front and signal that we need more
556 buffer
->need_more_
= true;
557 if (buffer
->state_
== ACE_COMMENT
)
564 buffer
->size_
= current
- buffer
->index_
;
565 if (buffer
->size_
!= 0 && buffer
->index_
!= 0)
566 ACE_OS::memmove (buffer
->input_
,
567 buffer
->input_
+ buffer
->index_
, buffer
->size_
);
569 buffer
->state_
= ACE_NO_STATE
;
575 #if defined (ACE_USES_WCHAR)
578 ACE_Svc_Conf_Lexer::convert_to_utf8 (
579 ACE_Svc_Conf_Param
* param
,
581 ACE_Encoding_Converter_Factory::Encoding_Hint hint
)
584 if (param
->buffer
->converter_
== 0)
586 param
->buffer
->converter_
=
587 ACE_Encoding_Converter_Factory::create (
588 reinterpret_cast<ACE_Byte
*> (param
->buffer
->input_
+ skip_bytes
),
589 param
->buffer
->size_
- skip_bytes
,
593 if (param
->buffer
->converter_
!= 0)
595 char target
[ACE_YY_CONVERSION_SPACE
] = "";
596 if (param
->buffer
->converter_
->to_utf8 (
597 param
->buffer
->input_
+ skip_bytes
,
598 param
->buffer
->size_
- skip_bytes
,
599 reinterpret_cast<ACE_Byte
*> (target
),
600 ACE_YY_CONVERSION_SPACE
) == ACE_Encoding_Converter::CONVERSION_OK
)
602 ACE_OS::strcpy (param
->buffer
->input_
+ skip_bytes
, target
);
603 param
->buffer
->size_
= ACE_OS::strlen (target
) + skip_bytes
;
612 ACE_Svc_Conf_Lexer::convert_from_utf8 (ACE_Encoding_Converter
* converter
,
621 if (converter
->from_utf8 (
622 reinterpret_cast <const ACE_Byte
*> (source
),
625 target_size
) != ACE_Encoding_Converter::CONVERSION_OK
)
632 ACE_OS::strncpy (target
, ACE_TEXT_CHAR_TO_TCHAR (source
), source_size
);
633 target
[source_size
] = 0;
636 length
= ACE_OS::strlen (target
);
640 ACE_Encoding_Converter_Factory::Encoding_Hint
641 ACE_Svc_Conf_Lexer::locate_bom (char* source
,
648 ACE_Encoding_Converter_Factory::Encoding_Hint hint_
;
650 static const bom boms
[] = {
651 { 4, "\x00\x00\xfe\xff", ACE_Encoding_Converter_Factory::ACE_UTF_32BE
},
652 { 4, "\xff\xfe\x00\x00", ACE_Encoding_Converter_Factory::ACE_UTF_32LE
},
653 { 2, "\xfe\xff", ACE_Encoding_Converter_Factory::ACE_UTF_16BE
},
654 { 2, "\xff\xfe", ACE_Encoding_Converter_Factory::ACE_UTF_16LE
},
655 { 3, "\xef\xbb\xbf", ACE_Encoding_Converter_Factory::ACE_UTF_8
},
658 for (size_t i
= 0; i
< sizeof (boms
) / sizeof (bom
); i
++)
660 if (source_size
>= boms
[i
].length_
)
662 if (ACE_OS::memcmp (source
,
663 boms
[i
].data_
, boms
[i
].length_
) == 0)
665 bytes_used
= boms
[i
].length_
;
666 return boms
[i
].hint_
;
673 return ACE_Encoding_Converter_Factory::ACE_NONE
;
676 #endif /* ACE_USES_WCHAR */
678 ACE_END_VERSIONED_NAMESPACE_DECL
679 #endif /* ACE_USES_CLASSIC_SVC_CONF = 1 */