gnuace: use list of generated files from GENERATED_DIRTY for ADDITIONAL_IDL_TARGETS
[ACE_TAO.git] / ACE / ace / Svc_Conf_Lexer.cpp
blob08d2f65d76bc56efbe9501a76b7a96a040104589
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"
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 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 (); \
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) && (_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
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 (void)
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) && (_MSC_VER >= 1400)
77 # pragma warning (pop)
78 #endif /* VC8 */
80 ~ace_yy_buffer_state (void)
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);
125 void
126 ace_yy_delete_buffer (ace_yy_buffer_state *buffer)
128 delete buffer;
131 // ******************************************************************
132 // Inline methods
133 // ******************************************************************
135 inline size_t
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 :
140 length);
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)
159 look_for_bom = true;
160 #endif /* ACE_USES_WCHAR */
161 ACE_NEW_RETURN (param->buffer,
162 ace_yy_buffer_state,
163 -1);
166 int token = ACE_NO_STATE;
167 do {
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;
174 size_t amount =
175 input (param,
176 param->buffer->input_ + param->buffer->size_,
177 normalize (ACE_YY_BUF_SIZE -
178 param->buffer->size_));
179 if (amount == 0)
181 param->buffer->eof_ = true;
182 #if defined (ACE_USES_WCHAR)
183 skip_bytes = param->buffer->size_;
184 #endif /* ACE_USES_WCHAR */
186 else
188 #if defined (ACE_USES_WCHAR)
189 if (look_for_bom)
191 size_t read_more = 0;
193 look_for_bom = false;
194 hint = locate_bom (param->buffer->input_, amount, read_more);
196 if (read_more != 0)
198 input (param,
199 param->buffer->input_ + amount,
200 read_more);
201 ACE_OS::memmove (param->buffer->input_,
202 param->buffer->input_ + read_more,
203 amount);
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,
215 param->yylineno,
216 ACE_TEXT ("Unable to convert input stream to UTF-8"));
217 return ACE_NO_STATE;
219 #endif /* ACE_USES_WCHAR */
222 token = scan (ace_yylval, param);
223 } while (token == ACE_NO_STATE && param->buffer->need_more_);
225 return token;
228 size_t
229 ACE_Svc_Conf_Lexer::input (ACE_Svc_Conf_Param* param,
230 char* buf, size_t max_size)
232 size_t result = 0;
234 switch (param->type)
236 case ACE_Svc_Conf_Param::SVC_CONF_FILE:
237 errno = 0;
238 while ((result = ACE_OS::fread (buf, 1,
239 max_size, param->source.file)) == 0 &&
240 ferror (param->source.file))
242 if (errno == EINTR)
244 errno = 0;
245 ACE_OS::clearerr (param->source.file);
247 else
249 #ifndef ACE_LACKS_STDERR
250 ACE_OS::fprintf (stderr, "ERROR: input in scanner failed\n");
251 #endif
252 ACE_OS::exit (2);
255 break;
256 case ACE_Svc_Conf_Param::SVC_CONF_DIRECTIVE:
257 result = ACE_OS::strlen (param->source.directive +
258 param->buffer->start_) * sizeof (ACE_TCHAR);
259 if (result != 0)
261 // Make sure that the amount we are going to copy
262 // fits in the buffer
263 if (result > max_size)
265 result = max_size;
267 ACE_OS::memcpy (buf,
268 param->source.directive + param->buffer->start_,
269 result);
270 param->buffer->start_ += (result / sizeof (ACE_TCHAR));
272 break;
273 default:
274 ace_yyerror (++param->yyerrno,
275 param->yylineno,
276 ACE_TEXT ("Invalid Service Configurator type in ")
277 ACE_TEXT ("ACE_Svc_Conf_Lexer::input"));
280 return result;
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')
299 ++param->yylineno;
301 ++buffer->index_;
305 size_t current;
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_)
314 case ACE_COMMENT:
315 if (c == '\n')
317 buffer->state_ = ACE_NO_STATE;
318 buffer->index_ = current + 1;
319 ++param->yylineno;
321 break;
322 case ACE_STRING:
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.
327 --current;
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;
343 break;
348 if (!string_end_found)
350 ace_yyerror (++param->yyerrno,
351 param->yylineno,
352 ACE_TEXT ("Unable to find the end of the string"));
353 return ACE_NO_STATE;
356 size_t amount = (current - buffer->index_) - 1;
357 #if defined (ACE_USES_WCHAR)
358 ACE_TCHAR target[ACE_YY_CONVERSION_SPACE] = ACE_TEXT ("");
359 size_t length = 0;
360 if (!convert_from_utf8 (buffer->converter_,
361 source,
362 amount,
363 target,
364 ACE_YY_CONVERSION_SPACE,
365 length))
367 ace_yyerror (++param->yyerrno,
368 param->yylineno,
369 ACE_TEXT ("Unable to convert string from UTF-8"));
370 return ACE_NO_STATE;
372 amount = length;
373 #else
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;
379 return ACE_STRING;
381 break;
382 case ACE_NO_STATE:
383 if (c == '"' || c == '\'')
385 buffer->string_start_ = c;
386 buffer->state_ = ACE_STRING;
388 else if (c == '#')
390 buffer->state_ = ACE_COMMENT;
392 else if (ACE_OS::strchr (separators, c) != 0)
394 if (c == '\n')
396 ++param->yylineno;
399 if (current == buffer->index_ + 1)
401 int const lower = ACE_OS::ace_tolower (
402 buffer->input_[current - 1]);
403 if (c == ':' &&
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
409 // again
410 break;
414 if (current == buffer->index_)
416 buffer->index_ = current + 1;
417 if (isspace (c))
419 // This is an empty line.
420 // Let's look for something else.
421 break;
423 else
425 return c;
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_,
433 size - 1);
434 str[size - 1] = '\0';
437 if (ACE_OS::strcmp (str, "dynamic") == 0)
439 buffer->index_ = current;
440 return ACE_DYNAMIC;
442 else if (ACE_OS::strcmp (str, "static") == 0)
444 buffer->index_ = current;
445 return ACE_STATIC;
447 else if (ACE_OS::strcmp (str, "suspend") == 0)
449 buffer->index_ = current;
450 return ACE_SUSPEND;
452 else if (ACE_OS::strcmp (str, "resume") == 0)
454 buffer->index_ = current;
455 return ACE_RESUME;
457 else if (ACE_OS::strcmp (str, "remove") == 0)
459 buffer->index_ = current;
460 return ACE_REMOVE;
462 else if (ACE_OS::strcmp (str, "stream") == 0)
464 buffer->index_ = current;
465 return ACE_USTREAM;
467 else if (ACE_OS::strcmp (str, "Module") == 0)
469 buffer->index_ = current;
470 return ACE_MODULE_T;
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;
480 return ACE_STREAM_T;
482 else if (ACE_OS::strcmp (str, "active") == 0)
484 buffer->index_ = current;
485 return ACE_ACTIVE;
487 else if (ACE_OS::strcmp (str, "inactive") == 0)
489 buffer->index_ = current;
490 return ACE_INACTIVE;
492 else
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 ("");
499 size_t length = 0;
500 if (!convert_from_utf8 (buffer->converter_,
501 str,
502 amount,
503 target,
504 ACE_YY_CONVERSION_SPACE,
505 length))
507 ace_yyerror (++param->yyerrno,
508 param->yylineno,
509 ACE_TEXT ("Unable to convert ")
510 ACE_TEXT ("identifier from UTF-8"));
511 return ACE_NO_STATE;
513 amount = length;
514 #else
515 char* target = str;
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;
524 else
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;
533 break;
538 buffer->state_ = ACE_NO_STATE;
539 buffer->index_ = current;
540 return token;
543 break;
544 default:
545 ace_yyerror (++param->yyerrno,
546 param->yylineno,
547 ACE_TEXT ("Unexpected state in ACE_Svc_Conf_Lexer::scan"));
548 return ACE_NO_STATE;
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
554 if (!buffer->eof_)
556 buffer->need_more_ = true;
557 if (buffer->state_ == ACE_COMMENT)
559 buffer->index_ = 0;
560 buffer->size_ = 0;
562 else
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_);
568 buffer->index_ = 0;
569 buffer->state_ = ACE_NO_STATE;
572 return ACE_NO_STATE;
575 #if defined (ACE_USES_WCHAR)
577 bool
578 ACE_Svc_Conf_Lexer::convert_to_utf8 (
579 ACE_Svc_Conf_Param* param,
580 size_t skip_bytes,
581 ACE_Encoding_Converter_Factory::Encoding_Hint hint)
583 bool status = false;
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,
590 hint);
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;
604 status = true;
608 return status;
611 bool
612 ACE_Svc_Conf_Lexer::convert_from_utf8 (ACE_Encoding_Converter* converter,
613 const char* source,
614 size_t source_size,
615 ACE_TCHAR* target,
616 size_t target_size,
617 size_t& length)
619 if (converter != 0)
621 if (converter->from_utf8 (
622 reinterpret_cast <const ACE_Byte*> (source),
623 source_size,
624 target,
625 target_size) != ACE_Encoding_Converter::CONVERSION_OK)
627 return false;
630 else
632 ACE_OS::strncpy (target, ACE_TEXT_CHAR_TO_TCHAR (source), source_size);
633 target[source_size] = 0;
636 length = ACE_OS::strlen (target);
637 return true;
640 ACE_Encoding_Converter_Factory::Encoding_Hint
641 ACE_Svc_Conf_Lexer::locate_bom (char* source,
642 size_t source_size,
643 size_t& bytes_used)
645 struct bom {
646 size_t length_;
647 const char* data_;
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_;
671 // No BOM was found
672 bytes_used = 0;
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 */