Initial Patch of Auction House bot rev. 135
[auctionmangos.git] / dep / ACE_wrappers / ace / Svc_Conf_Lexer.cpp
blobd83f23ede7e416316d1c37e93b3cca30a25ac819
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"
23 #endif
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]
34 #else
35 # define ACE_TEMPORARY_STRING(X,SIZE) \
36 char* X = 0; \
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 (); \
42 } \
43 else { \
44 X = X ## buf; \
46 #endif /* __GNUG__ */
48 // These are states not covered by the tokens in Svc_Conf_Tokens.h
49 #define ACE_NO_STATE -1
50 #define ACE_COMMENT 0
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
56 // warning here.
57 # pragma warning (push)
58 # pragma warning (disable:4351)
59 #endif /* VC8 */
61 struct ace_yy_buffer_state
63 ace_yy_buffer_state (void)
64 : input_ (),
65 index_ (0),
66 size_ (0),
67 start_ (0),
68 need_more_ (true),
69 eof_ (false),
70 state_ (ACE_NO_STATE),
71 string_start_ (0)
72 #if defined (ACE_USES_WCHAR)
73 , converter_ (0)
74 #endif /* ACE_USES_WCHAR */
77 #if defined (_MSC_VER) && (_MSC_VER >= 1400)
78 # pragma warning (pop)
79 #endif /* VC8 */
81 ~ace_yy_buffer_state (void)
83 #if defined (ACE_USES_WCHAR)
84 delete converter_;
85 #endif /* ACE_USES_WCHAR */
88 // Input related
89 char input_[ACE_YY_CONVERSION_SPACE];
90 size_t index_;
91 size_t size_;
92 size_t start_;
93 bool need_more_;
94 bool eof_;
96 // Parsing related
97 int state_;
98 char string_start_;
100 #if defined (ACE_USES_WCHAR)
101 // Code set conversion related
102 ACE_Encoding_Converter* converter_;
103 #endif /* ACE_USES_WCHAR */
106 // ******************************************************************
107 // Global functions
108 // ******************************************************************
111 ace_yylex (YYSTYPE *ace_yylval, void *YYLEX_PARAM)
113 ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_RECURSIVE_MUTEX,
114 ace_mon,
115 *ACE_Static_Object_Lock::instance (),
116 -1));
118 return ACE_Svc_Conf_Lexer::yylex (ace_yylval, ACE_SVC_CONF_PARAM);
122 void
123 ace_yy_delete_buffer (ace_yy_buffer_state *buffer)
125 delete buffer;
128 // ******************************************************************
129 // Inline methods
130 // ******************************************************************
132 inline size_t
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 :
137 length);
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)
156 look_for_bom = true;
157 #endif /* ACE_USES_WCHAR */
158 ACE_NEW_RETURN (param->buffer,
159 ace_yy_buffer_state,
160 -1);
163 int token = ACE_NO_STATE;
164 do {
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;
171 size_t amount =
172 input (param,
173 param->buffer->input_ + param->buffer->size_,
174 normalize (ACE_YY_BUF_SIZE -
175 param->buffer->size_));
176 if (amount == 0)
178 param->buffer->eof_ = true;
179 #if defined (ACE_USES_WCHAR)
180 skip_bytes = param->buffer->size_;
181 #endif /* ACE_USES_WCHAR */
183 else
185 #if defined (ACE_USES_WCHAR)
186 if (look_for_bom)
188 size_t read_more = 0;
190 look_for_bom = false;
191 hint = locate_bom (param->buffer->input_, amount, read_more);
193 if (read_more != 0)
195 input (param,
196 param->buffer->input_ + amount,
197 read_more);
198 ACE_OS::memmove (param->buffer->input_,
199 param->buffer->input_ + read_more,
200 amount);
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,
212 param->yylineno,
213 ACE_TEXT ("Unable to convert input stream to UTF-8"));
214 return ACE_NO_STATE;
216 #endif /* ACE_USES_WCHAR */
219 token = scan (ace_yylval, param);
220 } while (token == ACE_NO_STATE && param->buffer->need_more_);
222 return token;
225 size_t
226 ACE_Svc_Conf_Lexer::input (ACE_Svc_Conf_Param* param,
227 char* buf, size_t max_size)
229 size_t result = 0;
231 switch (param->type)
233 case ACE_Svc_Conf_Param::SVC_CONF_FILE:
234 errno = 0;
235 while ((result = ACE_OS::fread (buf, 1,
236 max_size, param->source.file)) == 0 &&
237 ferror (param->source.file))
239 if (errno == EINTR)
241 errno = 0;
242 #if !defined (ACE_LACKS_CLEARERR)
243 ACE_OS::clearerr (param->source.file);
244 #endif /* !ACE_LACKS_CLEARERR */
246 else
248 ACE_OS::fprintf (stderr, "ERROR: input in scanner failed\n");
249 ACE_OS::exit (2);
252 break;
253 case ACE_Svc_Conf_Param::SVC_CONF_DIRECTIVE:
254 result = ACE_OS::strlen (param->source.directive +
255 param->buffer->start_) * sizeof (ACE_TCHAR);
256 if (result != 0)
258 // Make sure that the amount we are going to copy
259 // fits in the buffer
260 if (result > max_size)
262 result = max_size;
264 ACE_OS::memcpy (buf,
265 param->source.directive + param->buffer->start_,
266 result);
267 param->buffer->start_ += (result / sizeof (ACE_TCHAR));
269 break;
270 default:
271 ace_yyerror (++param->yyerrno,
272 param->yylineno,
273 ACE_TEXT ("Invalid Service Configurator type in ")
274 ACE_TEXT ("ACE_Svc_Conf_Lexer::input"));
277 return result;
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')
296 ++param->yylineno;
298 ++buffer->index_;
302 size_t current;
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_)
311 case ACE_COMMENT:
312 if (c == '\n')
314 buffer->state_ = ACE_NO_STATE;
315 buffer->index_ = current + 1;
316 ++param->yylineno;
318 break;
319 case ACE_STRING:
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.
324 --current;
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;
340 break;
345 if (!string_end_found)
347 ace_yyerror (++param->yyerrno,
348 param->yylineno,
349 ACE_TEXT ("Unable to find the end of the string"));
350 return ACE_NO_STATE;
353 size_t amount = (current - buffer->index_) - 1;
354 #if defined (ACE_USES_WCHAR)
355 ACE_TCHAR target[ACE_YY_CONVERSION_SPACE] = ACE_TEXT ("");
356 size_t length = 0;
357 if (!convert_from_utf8 (buffer->converter_,
358 source,
359 amount,
360 target,
361 ACE_YY_CONVERSION_SPACE,
362 length))
364 ace_yyerror (++param->yyerrno,
365 param->yylineno,
366 ACE_TEXT ("Unable to convert string from UTF-8"));
367 return ACE_NO_STATE;
369 amount = length;
370 #else
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;
376 return ACE_STRING;
378 break;
379 case ACE_NO_STATE:
380 if (c == '"' || c == '\'')
382 buffer->string_start_ = c;
383 buffer->state_ = ACE_STRING;
385 else if (c == '#')
387 buffer->state_ = ACE_COMMENT;
389 else if (ACE_OS::strchr (separators, c) != 0)
391 if (c == '\n')
393 ++param->yylineno;
396 if (current == buffer->index_ + 1)
398 int lower = ACE_OS::ace_tolower (
399 buffer->input_[current - 1]);
400 if (c == ':' &&
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
406 // again
407 break;
411 if (current == buffer->index_)
413 buffer->index_ = current + 1;
414 if (isspace (c))
416 // This is an empty line.
417 // Let's look for something else.
418 break;
420 else
422 return c;
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_,
430 size - 1);
431 str[size - 1] = '\0';
434 if (ACE_OS::strcmp (str, "dynamic") == 0)
436 buffer->index_ = current;
437 return ACE_DYNAMIC;
439 else if (ACE_OS::strcmp (str, "static") == 0)
441 buffer->index_ = current;
442 return ACE_STATIC;
444 else if (ACE_OS::strcmp (str, "suspend") == 0)
446 buffer->index_ = current;
447 return ACE_SUSPEND;
449 else if (ACE_OS::strcmp (str, "resume") == 0)
451 buffer->index_ = current;
452 return ACE_RESUME;
454 else if (ACE_OS::strcmp (str, "remove") == 0)
456 buffer->index_ = current;
457 return ACE_REMOVE;
459 else if (ACE_OS::strcmp (str, "stream") == 0)
461 buffer->index_ = current;
462 return ACE_USTREAM;
464 else if (ACE_OS::strcmp (str, "Module") == 0)
466 buffer->index_ = current;
467 return ACE_MODULE_T;
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;
477 return ACE_STREAM_T;
479 else if (ACE_OS::strcmp (str, "active") == 0)
481 buffer->index_ = current;
482 return ACE_ACTIVE;
484 else if (ACE_OS::strcmp (str, "inactive") == 0)
486 buffer->index_ = current;
487 return ACE_INACTIVE;
489 else
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 ("");
496 size_t length = 0;
497 if (!convert_from_utf8 (buffer->converter_,
498 str,
499 amount,
500 target,
501 ACE_YY_CONVERSION_SPACE,
502 length))
504 ace_yyerror (++param->yyerrno,
505 param->yylineno,
506 ACE_TEXT ("Unable to convert ")
507 ACE_TEXT ("identifier from UTF-8"));
508 return ACE_NO_STATE;
510 amount = length;
511 #else
512 char* target = str;
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;
521 else
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;
530 break;
535 buffer->state_ = ACE_NO_STATE;
536 buffer->index_ = current;
537 return token;
540 break;
541 default:
542 ace_yyerror (++param->yyerrno,
543 param->yylineno,
544 ACE_TEXT ("Unexpected state in ACE_Svc_Conf_Lexer::scan"));
545 return ACE_NO_STATE;
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
551 if (!buffer->eof_)
553 buffer->need_more_ = true;
554 if (buffer->state_ == ACE_COMMENT)
556 buffer->index_ = 0;
557 buffer->size_ = 0;
559 else
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_);
565 buffer->index_ = 0;
566 buffer->state_ = ACE_NO_STATE;
569 return ACE_NO_STATE;
572 #if defined (ACE_USES_WCHAR)
574 bool
575 ACE_Svc_Conf_Lexer::convert_to_utf8 (
576 ACE_Svc_Conf_Param* param,
577 size_t skip_bytes,
578 ACE_Encoding_Converter_Factory::Encoding_Hint hint)
580 bool status = false;
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,
587 hint);
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;
601 status = true;
605 return status;
608 bool
609 ACE_Svc_Conf_Lexer::convert_from_utf8 (ACE_Encoding_Converter* converter,
610 const char* source,
611 size_t source_size,
612 ACE_TCHAR* target,
613 size_t target_size,
614 size_t& length)
616 if (converter != 0)
618 if (converter->from_utf8 (
619 reinterpret_cast <const ACE_Byte*> (source),
620 source_size,
621 target,
622 target_size) != ACE_Encoding_Converter::CONVERSION_OK)
624 return false;
627 else
629 ACE_OS::strncpy (target, ACE_TEXT_CHAR_TO_TCHAR (source), source_size);
630 target[source_size] = 0;
633 length = ACE_OS::strlen (target);
634 return true;
637 ACE_Encoding_Converter_Factory::Encoding_Hint
638 ACE_Svc_Conf_Lexer::locate_bom (char* source,
639 size_t source_size,
640 size_t& bytes_used)
642 struct bom {
643 size_t length_;
644 const char* data_;
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_;
668 // No BOM was found
669 bytes_used = 0;
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 */