1 // $Id: Svc_Conf_Lexer.cpp 81312 2008-04-09 21:01:34Z iliyan $
2 #include "ace/Svc_Conf_Lexer.h"
4 #if (ACE_USES_CLASSIC_SVC_CONF == 1)
6 #if defined (ACE_USES_WCHAR)
7 #include "ace/Encoding_Converter.h"
8 #include "ace/Encoding_Converter_Factory.h"
9 #endif /* ACE_USES_WCHAR */
11 #include "ace/Svc_Conf_Tokens.h"
12 #include "ace/Recursive_Thread_Mutex.h"
13 #include "ace/Static_Object_Lock.h"
14 #include "ace/OS_NS_stdio.h"
15 #include "ace/OS_NS_ctype.h"
16 #include "ace/OS_NS_string.h"
17 #include "ace/Guard_T.h"
18 #include "ace/Synch_Traits.h"
19 #include "ace/os_include/os_ctype.h"
21 #if !defined (__GNUG__)
22 # include "ace/Auto_Ptr.h"
25 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
27 #define ACE_YY_BUF_SIZE 4096
28 #define ACE_MAX_BYTES_PER_CHAR 4
29 #define ACE_YY_CONVERSION_SPACE ACE_YY_BUF_SIZE * ACE_MAX_BYTES_PER_CHAR
31 #if defined (__GNUG__)
32 # define ACE_TEMPORARY_STRING(X,SIZE) \
33 __extension__ char X[SIZE]
35 # define ACE_TEMPORARY_STRING(X,SIZE) \
37 char X ## buf[ACE_YY_BUF_SIZE]; \
38 ACE_Auto_Ptr<char> X ## bufp (0); \
39 if (SIZE > ACE_YY_BUF_SIZE) { \
40 X ## bufp.reset (new char[SIZE]); \
41 X = X ## bufp.get (); \
48 // These are states not covered by the tokens in Svc_Conf_Tokens.h
49 #define ACE_NO_STATE -1
52 #if defined (_MSC_VER) && (_MSC_VER >= 1400)
53 // Visual Studio .NET 2005 (VC8) issues warning C4351 for input_ in the
54 // constructor initializer list below. Since we like the warned-of new
55 // behavior (input_ elements will be default-initialized), squash the
57 # pragma warning (push)
58 # pragma warning (disable:4351)
61 struct ace_yy_buffer_state
63 ace_yy_buffer_state (void)
70 state_ (ACE_NO_STATE
),
72 #if defined (ACE_USES_WCHAR)
74 #endif /* ACE_USES_WCHAR */
77 #if defined (_MSC_VER) && (_MSC_VER >= 1400)
78 # pragma warning (pop)
81 ~ace_yy_buffer_state (void)
83 #if defined (ACE_USES_WCHAR)
85 #endif /* ACE_USES_WCHAR */
89 char input_
[ACE_YY_CONVERSION_SPACE
];
100 #if defined (ACE_USES_WCHAR)
101 // Code set conversion related
102 ACE_Encoding_Converter
* converter_
;
103 #endif /* ACE_USES_WCHAR */
106 // ******************************************************************
108 // ******************************************************************
111 ace_yylex (YYSTYPE
*ace_yylval
, void *YYLEX_PARAM
)
113 ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_RECURSIVE_MUTEX
,
115 *ACE_Static_Object_Lock::instance (),
118 return ACE_Svc_Conf_Lexer::yylex (ace_yylval
, ACE_SVC_CONF_PARAM
);
123 ace_yy_delete_buffer (ace_yy_buffer_state
*buffer
)
128 // ******************************************************************
130 // ******************************************************************
133 normalize (size_t length
)
135 return (length
>= ACE_MAX_BYTES_PER_CHAR
?
136 (length
/ ACE_MAX_BYTES_PER_CHAR
) * ACE_MAX_BYTES_PER_CHAR
:
140 // ******************************************************************
141 // Static class methods
142 // ******************************************************************
145 ACE_Svc_Conf_Lexer::yylex (YYSTYPE
* ace_yylval
,
146 ACE_Svc_Conf_Param
* param
)
148 #if defined (ACE_USES_WCHAR)
149 bool look_for_bom
= false;
150 ACE_Encoding_Converter_Factory::Encoding_Hint hint
=
151 ACE_Encoding_Converter_Factory::ACE_NONE
;
152 #endif /* ACE_USES_WCHAR */
153 if (param
->buffer
== 0)
155 #if defined (ACE_USES_WCHAR)
157 #endif /* ACE_USES_WCHAR */
158 ACE_NEW_RETURN (param
->buffer
,
163 int token
= ACE_NO_STATE
;
165 if (param
->buffer
->need_more_
)
167 #if defined (ACE_USES_WCHAR)
168 size_t skip_bytes
= 0;
169 #endif /* ACE_USES_WCHAR */
170 param
->buffer
->need_more_
= false;
173 param
->buffer
->input_
+ param
->buffer
->size_
,
174 normalize (ACE_YY_BUF_SIZE
-
175 param
->buffer
->size_
));
178 param
->buffer
->eof_
= true;
179 #if defined (ACE_USES_WCHAR)
180 skip_bytes
= param
->buffer
->size_
;
181 #endif /* ACE_USES_WCHAR */
185 #if defined (ACE_USES_WCHAR)
188 size_t read_more
= 0;
190 look_for_bom
= false;
191 hint
= locate_bom (param
->buffer
->input_
, amount
, read_more
);
196 param
->buffer
->input_
+ amount
,
198 ACE_OS::memmove (param
->buffer
->input_
,
199 param
->buffer
->input_
+ read_more
,
203 skip_bytes
= param
->buffer
->size_
;
204 #endif /* ACE_USES_WCHAR */
205 param
->buffer
->size_
+= amount
;
208 #if defined (ACE_USES_WCHAR)
209 if (!convert_to_utf8 (param
, skip_bytes
, hint
))
211 ace_yyerror (++param
->yyerrno
,
213 ACE_TEXT ("Unable to convert input stream to UTF-8"));
216 #endif /* ACE_USES_WCHAR */
219 token
= scan (ace_yylval
, param
);
220 } while (token
== ACE_NO_STATE
&& param
->buffer
->need_more_
);
226 ACE_Svc_Conf_Lexer::input (ACE_Svc_Conf_Param
* param
,
227 char* buf
, size_t max_size
)
233 case ACE_Svc_Conf_Param::SVC_CONF_FILE
:
235 while ((result
= ACE_OS::fread (buf
, 1,
236 max_size
, param
->source
.file
)) == 0 &&
237 ferror (param
->source
.file
))
242 #if !defined (ACE_LACKS_CLEARERR)
243 ACE_OS::clearerr (param
->source
.file
);
244 #endif /* !ACE_LACKS_CLEARERR */
248 ACE_OS::fprintf (stderr
, "ERROR: input in scanner failed\n");
253 case ACE_Svc_Conf_Param::SVC_CONF_DIRECTIVE
:
254 result
= ACE_OS::strlen (param
->source
.directive
+
255 param
->buffer
->start_
) * sizeof (ACE_TCHAR
);
258 // Make sure that the amount we are going to copy
259 // fits in the buffer
260 if (result
> max_size
)
265 param
->source
.directive
+ param
->buffer
->start_
,
267 param
->buffer
->start_
+= (result
/ sizeof (ACE_TCHAR
));
271 ace_yyerror (++param
->yyerrno
,
273 ACE_TEXT ("Invalid Service Configurator type in ")
274 ACE_TEXT ("ACE_Svc_Conf_Lexer::input"));
281 ACE_Svc_Conf_Lexer::scan (YYSTYPE
* ace_yylval
,
282 ACE_Svc_Conf_Param
* param
)
285 ace_yy_buffer_state
* buffer
= param
->buffer
;
287 // If we are not currently in any state, skip over whitespace
288 if (buffer
->state_
== ACE_NO_STATE
)
290 while (buffer
->index_
< buffer
->size_
&&
291 isspace (buffer
->input_
[buffer
->index_
]))
293 // Make sure that we count all of the new lines
294 if (buffer
->input_
[buffer
->index_
] == '\n')
303 size_t last
= buffer
->size_
+ (buffer
->eof_
? 1 : 0);
304 for (current
= buffer
->index_
; current
< last
; current
++)
306 static const char* separators
= " \t\r\n:*(){}";
307 char c
= (buffer
->eof_
&& current
== buffer
->size_
?
308 '\n' : buffer
->input_
[current
]);
309 switch (buffer
->state_
)
314 buffer
->state_
= ACE_NO_STATE
;
315 buffer
->index_
= current
+ 1;
320 if (!(c
>= ' ' && c
<= '~'))
322 // The character at currrent is definitely not part of
323 // the string so we need to move current back one.
326 // Get the starting point of our string (skipping the quote)
327 char* source
= buffer
->input_
+ buffer
->index_
+ 1;
329 // Now, we need to move back in the string until we find the
330 // same character that started the string
331 bool string_end_found
= false;
332 if (current
> buffer
->index_
)
334 for (size_t i
= current
- buffer
->index_
; i
-- != 0; )
336 if (source
[i
] == buffer
->string_start_
)
338 current
= buffer
->index_
+ i
+ 1;
339 string_end_found
= true;
345 if (!string_end_found
)
347 ace_yyerror (++param
->yyerrno
,
349 ACE_TEXT ("Unable to find the end of the string"));
353 size_t amount
= (current
- buffer
->index_
) - 1;
354 #if defined (ACE_USES_WCHAR)
355 ACE_TCHAR target
[ACE_YY_CONVERSION_SPACE
] = ACE_TEXT ("");
357 if (!convert_from_utf8 (buffer
->converter_
,
361 ACE_YY_CONVERSION_SPACE
,
364 ace_yyerror (++param
->yyerrno
,
366 ACE_TEXT ("Unable to convert string from UTF-8"));
371 char* target
= source
;
372 #endif /* ACE_USES_WCHAR */
373 ace_yylval
->ident_
= param
->obstack
.copy (target
, amount
);
374 buffer
->state_
= ACE_NO_STATE
;
375 buffer
->index_
= current
+ 1;
380 if (c
== '"' || c
== '\'')
382 buffer
->string_start_
= c
;
383 buffer
->state_
= ACE_STRING
;
387 buffer
->state_
= ACE_COMMENT
;
389 else if (ACE_OS::strchr (separators
, c
) != 0)
396 if (current
== buffer
->index_
+ 1)
398 int lower
= ACE_OS::ace_tolower (
399 buffer
->input_
[current
- 1]);
401 (buffer
->input_
[current
- 1] == '%' ||
402 (lower
>= 'a' && lower
<= 'z')))
404 // This is considered a path, so we need to
405 // skip over the ':' and go around the loop
411 if (current
== buffer
->index_
)
413 buffer
->index_
= current
+ 1;
416 // This is an empty line.
417 // Let's look for something else.
426 // String from buffer->index_ to current (inclusive)
427 size_t size
= (current
- buffer
->index_
) + 1;
428 ACE_TEMPORARY_STRING (str
, size
);
429 ACE_OS::strncpy (str
, buffer
->input_
+ buffer
->index_
,
431 str
[size
- 1] = '\0';
434 if (ACE_OS::strcmp (str
, "dynamic") == 0)
436 buffer
->index_
= current
;
439 else if (ACE_OS::strcmp (str
, "static") == 0)
441 buffer
->index_
= current
;
444 else if (ACE_OS::strcmp (str
, "suspend") == 0)
446 buffer
->index_
= current
;
449 else if (ACE_OS::strcmp (str
, "resume") == 0)
451 buffer
->index_
= current
;
454 else if (ACE_OS::strcmp (str
, "remove") == 0)
456 buffer
->index_
= current
;
459 else if (ACE_OS::strcmp (str
, "stream") == 0)
461 buffer
->index_
= current
;
464 else if (ACE_OS::strcmp (str
, "Module") == 0)
466 buffer
->index_
= current
;
469 else if (ACE_OS::strcmp (str
, "Service_Object") == 0)
471 buffer
->index_
= current
;
472 return ACE_SVC_OBJ_T
;
474 else if (ACE_OS::strcmp (str
, "STREAM") == 0)
476 buffer
->index_
= current
;
479 else if (ACE_OS::strcmp (str
, "active") == 0)
481 buffer
->index_
= current
;
484 else if (ACE_OS::strcmp (str
, "inactive") == 0)
486 buffer
->index_
= current
;
491 // Get the string and save it in ace_yylval
492 int token
= ACE_IDENT
;
493 size_t amount
= size
- 1;
494 #if defined (ACE_USES_WCHAR)
495 ACE_TCHAR target
[ACE_YY_CONVERSION_SPACE
] = ACE_TEXT ("");
497 if (!convert_from_utf8 (buffer
->converter_
,
501 ACE_YY_CONVERSION_SPACE
,
504 ace_yyerror (++param
->yyerrno
,
506 ACE_TEXT ("Unable to convert ")
507 ACE_TEXT ("identifier from UTF-8"));
513 #endif /* ACE_USES_WCHAR */
514 ace_yylval
->ident_
= param
->obstack
.copy (target
, amount
);
516 // Determine the difference between pathname and ident
517 if (ACE_OS::ace_isdigit (ace_yylval
->ident_
[0]))
519 token
= ACE_PATHNAME
;
523 static const ACE_TCHAR
* path_parts
=
524 ACE_TEXT ("/\\:%.~-");
525 for (const ACE_TCHAR
* p
= path_parts
; *p
!= '\0'; p
++)
527 if (ACE_OS::strchr (ace_yylval
->ident_
, *p
) != 0)
529 token
= ACE_PATHNAME
;
535 buffer
->state_
= ACE_NO_STATE
;
536 buffer
->index_
= current
;
542 ace_yyerror (++param
->yyerrno
,
544 ACE_TEXT ("Unexpected state in ACE_Svc_Conf_Lexer::scan"));
549 // We need more from the input source so, we will move the remainder of
550 // the buffer to the front and signal that we need more
553 buffer
->need_more_
= true;
554 if (buffer
->state_
== ACE_COMMENT
)
561 buffer
->size_
= current
- buffer
->index_
;
562 if (buffer
->size_
!= 0 && buffer
->index_
!= 0)
563 ACE_OS::memmove (buffer
->input_
,
564 buffer
->input_
+ buffer
->index_
, buffer
->size_
);
566 buffer
->state_
= ACE_NO_STATE
;
572 #if defined (ACE_USES_WCHAR)
575 ACE_Svc_Conf_Lexer::convert_to_utf8 (
576 ACE_Svc_Conf_Param
* param
,
578 ACE_Encoding_Converter_Factory::Encoding_Hint hint
)
581 if (param
->buffer
->converter_
== 0)
583 param
->buffer
->converter_
=
584 ACE_Encoding_Converter_Factory::create (
585 reinterpret_cast<ACE_Byte
*> (param
->buffer
->input_
+ skip_bytes
),
586 param
->buffer
->size_
- skip_bytes
,
590 if (param
->buffer
->converter_
!= 0)
592 char target
[ACE_YY_CONVERSION_SPACE
] = "";
593 if (param
->buffer
->converter_
->to_utf8 (
594 param
->buffer
->input_
+ skip_bytes
,
595 param
->buffer
->size_
- skip_bytes
,
596 reinterpret_cast<ACE_Byte
*> (target
),
597 ACE_YY_CONVERSION_SPACE
) == ACE_Encoding_Converter::CONVERSION_OK
)
599 ACE_OS::strcpy (param
->buffer
->input_
+ skip_bytes
, target
);
600 param
->buffer
->size_
= ACE_OS::strlen (target
) + skip_bytes
;
609 ACE_Svc_Conf_Lexer::convert_from_utf8 (ACE_Encoding_Converter
* converter
,
618 if (converter
->from_utf8 (
619 reinterpret_cast <const ACE_Byte
*> (source
),
622 target_size
) != ACE_Encoding_Converter::CONVERSION_OK
)
629 ACE_OS::strncpy (target
, ACE_TEXT_CHAR_TO_TCHAR (source
), source_size
);
630 target
[source_size
] = 0;
633 length
= ACE_OS::strlen (target
);
637 ACE_Encoding_Converter_Factory::Encoding_Hint
638 ACE_Svc_Conf_Lexer::locate_bom (char* source
,
645 ACE_Encoding_Converter_Factory::Encoding_Hint hint_
;
647 static const bom boms
[] = {
648 { 4, "\x00\x00\xfe\xff", ACE_Encoding_Converter_Factory::ACE_UTF_32BE
},
649 { 4, "\xff\xfe\x00\x00", ACE_Encoding_Converter_Factory::ACE_UTF_32LE
},
650 { 2, "\xfe\xff", ACE_Encoding_Converter_Factory::ACE_UTF_16BE
},
651 { 2, "\xff\xfe", ACE_Encoding_Converter_Factory::ACE_UTF_16LE
},
652 { 3, "\xef\xbb\xbf", ACE_Encoding_Converter_Factory::ACE_UTF_8
},
655 for (size_t i
= 0; i
< sizeof (boms
) / sizeof (bom
); i
++)
657 if (source_size
>= boms
[i
].length_
)
659 if (ACE_OS::memcmp (source
,
660 boms
[i
].data_
, boms
[i
].length_
) == 0)
662 bytes_used
= boms
[i
].length_
;
663 return boms
[i
].hint_
;
670 return ACE_Encoding_Converter_Factory::ACE_NONE
;
673 #endif /* ACE_USES_WCHAR */
675 ACE_END_VERSIONED_NAMESPACE_DECL
676 #endif /* ACE_USES_CLASSIC_SVC_CONF = 1 */