Changes to attempt to silence bcc64x
[ACE_TAO.git] / ACE / ace / Svc_Conf_Lexer.cpp
blob3c408d5e0249de12cf1625ee9d678f297cf21a58
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 <memory>
22 #endif
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]
33 #else
34 # define ACE_TEMPORARY_STRING(X,SIZE) \
35 char* X = 0; \
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 (); \
41 } \
42 else { \
43 X = X ## buf; \
45 #endif /* __GNUG__ */
47 // These are states not covered by the tokens in Svc_Conf_Tokens.h
48 #define ACE_NO_STATE -1
49 #define ACE_COMMENT 0
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
55 // warning here.
56 # pragma warning (push)
57 # pragma warning (disable:4351)
58 #endif /* VC8 */
60 struct ace_yy_buffer_state
62 ace_yy_buffer_state ()
63 : input_ (),
64 index_ (0),
65 size_ (0),
66 start_ (0),
67 need_more_ (true),
68 eof_ (false),
69 state_ (ACE_NO_STATE),
70 string_start_ (0)
71 #if defined (ACE_USES_WCHAR)
72 , converter_ (0)
73 #endif /* ACE_USES_WCHAR */
76 #if defined (_MSC_VER)
77 # pragma warning (pop)
78 #endif /* VC8 */
80 ~ace_yy_buffer_state ()
82 #if defined (ACE_USES_WCHAR)
83 delete converter_;
84 #endif /* ACE_USES_WCHAR */
87 ACE_ALLOC_HOOK_DECLARE;
89 // Input related
90 char input_[ACE_YY_CONVERSION_SPACE];
91 size_t index_;
92 size_t size_;
93 size_t start_;
94 bool need_more_;
95 bool eof_;
97 // Parsing related
98 int state_;
99 char string_start_;
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 // ******************************************************************
110 // Global functions
111 // ******************************************************************
114 ace_yylex (YYSTYPE *ace_yylval, void *YYLEX_PARAM)
116 ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_RECURSIVE_MUTEX,
117 ace_mon,
118 *ACE_Static_Object_Lock::instance (),
119 -1));
121 return ACE_Svc_Conf_Lexer::yylex (ace_yylval, ACE_SVC_CONF_PARAM);
124 void
125 ace_yy_delete_buffer (ace_yy_buffer_state *buffer)
127 delete buffer;
130 // ******************************************************************
131 // Inline methods
132 // ******************************************************************
134 inline size_t
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 :
139 length);
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)
158 look_for_bom = true;
159 #endif /* ACE_USES_WCHAR */
160 ACE_NEW_RETURN (param->buffer,
161 ace_yy_buffer_state,
162 -1);
165 int token = ACE_NO_STATE;
166 do {
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;
173 size_t amount =
174 input (param,
175 param->buffer->input_ + param->buffer->size_,
176 normalize (ACE_YY_BUF_SIZE -
177 param->buffer->size_));
178 if (amount == 0)
180 param->buffer->eof_ = true;
181 #if defined (ACE_USES_WCHAR)
182 skip_bytes = param->buffer->size_;
183 #endif /* ACE_USES_WCHAR */
185 else
187 #if defined (ACE_USES_WCHAR)
188 if (look_for_bom)
190 size_t read_more = 0;
192 look_for_bom = false;
193 hint = locate_bom (param->buffer->input_, amount, read_more);
195 if (read_more != 0)
197 input (param,
198 param->buffer->input_ + amount,
199 read_more);
200 ACE_OS::memmove (param->buffer->input_,
201 param->buffer->input_ + read_more,
202 amount);
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,
214 param->yylineno,
215 ACE_TEXT ("Unable to convert input stream to UTF-8"));
216 return ACE_NO_STATE;
218 #endif /* ACE_USES_WCHAR */
221 token = scan (ace_yylval, param);
222 } while (token == ACE_NO_STATE && param->buffer->need_more_);
224 return token;
227 size_t
228 ACE_Svc_Conf_Lexer::input (ACE_Svc_Conf_Param* param,
229 char* buf, size_t max_size)
231 size_t result = 0;
233 switch (param->type)
235 case ACE_Svc_Conf_Param::SVC_CONF_FILE:
236 errno = 0;
237 while ((result = ACE_OS::fread (buf, 1,
238 max_size, param->source.file)) == 0 &&
239 ferror (param->source.file))
241 if (errno == EINTR)
243 errno = 0;
244 ACE_OS::clearerr (param->source.file);
246 else
248 #ifndef ACE_LACKS_STDERR
249 ACE_OS::fprintf (stderr, "ERROR: input in scanner failed\n");
250 #endif
251 ACE_OS::exit (2);
254 break;
255 case ACE_Svc_Conf_Param::SVC_CONF_DIRECTIVE:
256 result = ACE_OS::strlen (param->source.directive +
257 param->buffer->start_) * sizeof (ACE_TCHAR);
258 if (result != 0)
260 // Make sure that the amount we are going to copy
261 // fits in the buffer
262 if (result > max_size)
264 result = max_size;
266 ACE_OS::memcpy (buf,
267 param->source.directive + param->buffer->start_,
268 result);
269 param->buffer->start_ += (result / sizeof (ACE_TCHAR));
271 break;
272 default:
273 ace_yyerror (++param->yyerrno,
274 param->yylineno,
275 ACE_TEXT ("Invalid Service Configurator type in ")
276 ACE_TEXT ("ACE_Svc_Conf_Lexer::input"));
279 return result;
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')
298 ++param->yylineno;
300 ++buffer->index_;
304 size_t current;
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_)
313 case ACE_COMMENT:
314 if (c == '\n')
316 buffer->state_ = ACE_NO_STATE;
317 buffer->index_ = current + 1;
318 ++param->yylineno;
320 break;
321 case ACE_STRING:
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.
326 --current;
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;
342 break;
347 if (!string_end_found)
349 ace_yyerror (++param->yyerrno,
350 param->yylineno,
351 ACE_TEXT ("Unable to find the end of the string"));
352 return ACE_NO_STATE;
355 size_t amount = (current - buffer->index_) - 1;
356 #if defined (ACE_USES_WCHAR)
357 ACE_TCHAR target[ACE_YY_CONVERSION_SPACE] = ACE_TEXT ("");
358 size_t length = 0;
359 if (!convert_from_utf8 (buffer->converter_,
360 source,
361 amount,
362 target,
363 ACE_YY_CONVERSION_SPACE,
364 length))
366 ace_yyerror (++param->yyerrno,
367 param->yylineno,
368 ACE_TEXT ("Unable to convert string from UTF-8"));
369 return ACE_NO_STATE;
371 amount = length;
372 #else
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;
378 return ACE_STRING;
380 break;
381 case ACE_NO_STATE:
382 if (c == '"' || c == '\'')
384 buffer->string_start_ = c;
385 buffer->state_ = ACE_STRING;
387 else if (c == '#')
389 buffer->state_ = ACE_COMMENT;
391 else if (ACE_OS::strchr (separators, c) != 0)
393 if (c == '\n')
395 ++param->yylineno;
398 if (current == buffer->index_ + 1)
400 int const lower = ACE_OS::ace_tolower (
401 buffer->input_[current - 1]);
402 if (c == ':' &&
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
408 // again
409 break;
413 if (current == buffer->index_)
415 buffer->index_ = current + 1;
416 if (isspace (c))
418 // This is an empty line.
419 // Let's look for something else.
420 break;
422 else
424 return c;
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_,
432 size - 1);
433 str[size - 1] = '\0';
436 if (ACE_OS::strcmp (str, "dynamic") == 0)
438 buffer->index_ = current;
439 return ACE_DYNAMIC;
441 else if (ACE_OS::strcmp (str, "static") == 0)
443 buffer->index_ = current;
444 return ACE_STATIC;
446 else if (ACE_OS::strcmp (str, "suspend") == 0)
448 buffer->index_ = current;
449 return ACE_SUSPEND;
451 else if (ACE_OS::strcmp (str, "resume") == 0)
453 buffer->index_ = current;
454 return ACE_RESUME;
456 else if (ACE_OS::strcmp (str, "remove") == 0)
458 buffer->index_ = current;
459 return ACE_REMOVE;
461 else if (ACE_OS::strcmp (str, "stream") == 0)
463 buffer->index_ = current;
464 return ACE_USTREAM;
466 else if (ACE_OS::strcmp (str, "Module") == 0)
468 buffer->index_ = current;
469 return ACE_MODULE_T;
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;
479 return ACE_STREAM_T;
481 else if (ACE_OS::strcmp (str, "active") == 0)
483 buffer->index_ = current;
484 return ACE_ACTIVE;
486 else if (ACE_OS::strcmp (str, "inactive") == 0)
488 buffer->index_ = current;
489 return ACE_INACTIVE;
491 else
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 ("");
498 size_t length = 0;
499 if (!convert_from_utf8 (buffer->converter_,
500 str,
501 amount,
502 target,
503 ACE_YY_CONVERSION_SPACE,
504 length))
506 ace_yyerror (++param->yyerrno,
507 param->yylineno,
508 ACE_TEXT ("Unable to convert ")
509 ACE_TEXT ("identifier from UTF-8"));
510 return ACE_NO_STATE;
512 amount = length;
513 #else
514 char* target = str;
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;
523 else
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;
532 break;
537 buffer->state_ = ACE_NO_STATE;
538 buffer->index_ = current;
539 return token;
542 break;
543 default:
544 ace_yyerror (++param->yyerrno,
545 param->yylineno,
546 ACE_TEXT ("Unexpected state in ACE_Svc_Conf_Lexer::scan"));
547 return ACE_NO_STATE;
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
553 if (!buffer->eof_)
555 buffer->need_more_ = true;
556 if (buffer->state_ == ACE_COMMENT)
558 buffer->index_ = 0;
559 buffer->size_ = 0;
561 else
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_);
567 buffer->index_ = 0;
568 buffer->state_ = ACE_NO_STATE;
571 return ACE_NO_STATE;
574 #if defined (ACE_USES_WCHAR)
576 bool
577 ACE_Svc_Conf_Lexer::convert_to_utf8 (
578 ACE_Svc_Conf_Param* param,
579 size_t skip_bytes,
580 ACE_Encoding_Converter_Factory::Encoding_Hint hint)
582 bool status = false;
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,
589 hint);
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;
603 status = true;
607 return status;
610 bool
611 ACE_Svc_Conf_Lexer::convert_from_utf8 (ACE_Encoding_Converter* converter,
612 const char* source,
613 size_t source_size,
614 ACE_TCHAR* target,
615 size_t target_size,
616 size_t& length)
618 if (converter != 0)
620 if (converter->from_utf8 (
621 reinterpret_cast <const ACE_Byte*> (source),
622 source_size,
623 target,
624 target_size) != ACE_Encoding_Converter::CONVERSION_OK)
626 return false;
629 else
631 ACE_OS::strncpy (target, ACE_TEXT_CHAR_TO_TCHAR (source), source_size);
632 target[source_size] = 0;
635 length = ACE_OS::strlen (target);
636 return true;
639 ACE_Encoding_Converter_Factory::Encoding_Hint
640 ACE_Svc_Conf_Lexer::locate_bom (char* source,
641 size_t source_size,
642 size_t& bytes_used)
644 struct bom {
645 size_t length_;
646 const char* data_;
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_;
670 // No BOM was found
671 bytes_used = 0;
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 */