Merge pull request #1815 from sonndinh/get_signal_info
[ACE_TAO.git] / TAO / TAO_IDL / fe / idl.ll
blob56ad0cbd63f61f4d32103f6397e40abc4efcce1d
1 %{
2 /*
4 COPYRIGHT
6 Copyright 1992, 1993, 1994 Sun Microsystems, Inc.  Printed in the United
7 States of America.  All Rights Reserved.
9 This product is protected by copyright and distributed under the following
10 license restricting its use.
12 The Interface Definition Language Compiler Front End (CFE) is made
13 available for your use provided that you include this license and copyright
14 notice on all media and documentation and the software program in which
15 this product is incorporated in whole or part. You may copy and extend
16 functionality (but may not remove functionality) of the Interface
17 Definition Language CFE without charge, but you are not authorized to
18 license or distribute it to anyone else except as part of a product or
19 program developed by you or with the express written consent of Sun
20 Microsystems, Inc. ("Sun").
22 The names of Sun Microsystems, Inc. and any of its subsidiaries or
23 affiliates may not be used in advertising or publicity pertaining to
24 distribution of Interface Definition Language CFE as permitted herein.
26 This license is effective until terminated by Sun for failure to comply
27 with this license.  Upon termination, you shall destroy or return all code
28 and documentation for the Interface Definition Language CFE.
30 IDL_INTERFACE DEFINITION LANGUAGE CFE IS PROVIDED AS IS WITH NO WARRANTIES OF
31 IDL_ANY KIND INCLUDING THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS
32 FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR ARISING FROM A COURSE OF
33 DEALING, USAGE OR TRADE PRACTICE.
35 IDL_INTERFACE DEFINITION LANGUAGE CFE IS PROVIDED WITH NO SUPPORT AND WITHOUT
36 IDL_ANY OBLIGATION ON THE PART OF Sun OR IDL_ANY OF ITS SUBSIDIARIES OR AFFILIATES
37 TO ASSIST IDL_IN ITS USE, CORRECTION, MODIFICATION OR ENHANCEMENT.
39 SUN OR IDL_ANY OF ITS SUBSIDIARIES OR AFFILIATES SHALL HAVE NO LIABILITY WITH
40 RESPECT TO THE INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR IDL_ANY PATENTS BY
41 IDL_INTERFACE DEFINITION LANGUAGE CFE OR IDL_ANY PART THEREOF.
43 IDL_IN NO EVENT WILL SUN OR IDL_ANY OF ITS SUBSIDIARIES OR AFFILIATES BE LIABLE FOR
44 IDL_ANY LOST REVENUE OR PROFITS OR OTHER SPECIAL, INDIRECT AND CONSEQUENTIAL
45 DAMAGES, EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
47 Use, duplication, or disclosure by the government is subject to
48 restrictions as set forth in subparagraph (c)(1)(ii) of the Rights in
49 Technical Data and Computer Software clause at DFARS 252.227-7013 and FAR
50 52.227-19.
52 Sun, Sun Microsystems and the Sun logo are trademarks or registered
53 trademarks of Sun Microsystems, Inc.
55 SunSoft, Inc.
56 2550 Garcia Avenue
57 Mountain View, California  94043
59 NOTE:
61 SunOS, SunSoft, Sun, Solaris, Sun Microsystems or the Sun logo are
62 trademarks or registered trademarks of Sun Microsystems, Inc.
64  */
67  * idl.ll - Lexical scanner for IDL
68  */
70 #include "global_extern.h"
71 #include "nr_extern.h"
72 #include "utl_strlist.h"
73 #include "utl_exprlist.h"
74 #include "utl_labellist.h"
75 #include "utl_decllist.h"
76 #include "utl_string.h"
77 #include "utl_err.h"
78 #include "ast_union_label.h"
79 #include "ast_field.h"
80 #include "ast_expression.h"
81 #include "ast_argument.h"
82 #include "ast_operation.h"
83 #include "ast_root.h"
84 #include "fe_interface_header.h"
85 #include "fe_obv_header.h"
86 #include "fe_component_header.h"
87 #include "fe_home_header.h"
88 #include "fe_private.h"
89 #include "fe_extern.h"
90 #include "ast_annotation_appl.h"
91 #include "idl.tab.hpp"
93 static char *               idl_wstring_escape_reader (char *);
94 static ACE_CDR::WChar       idl_wchar_escape_reader (char *);
95 static ACE_CDR::Char        idl_escape_reader (char *);
96 static ACE_CDR::Double      idl_atof (char *);
97 static ACE_CDR::LongLong    idl_atoi (char *, long);
98 static ACE_CDR::ULongLong   idl_atoui (char *, long);
99 static void                 idl_parse_line_and_file (char *);
100 static void                 idl_store_pragma (char *);
101 static char *               idl_get_pragma_string (char *);
102 static bool                 idl_valid_version (char *);
103 static AST_Decl *           idl_find_node (const char *);
105 #define ace_yytext yytext
107 #ifdef USE_MCPP_BUFFER_LEXING
108 #include "mcpp_yyinput.h"
109 #endif /*USE_MCPP_BUFFER_LEXING*/
111 #if defined __ANDROID__ && defined ECHO
112 #undef ECHO
113 #endif
117 /* SO we don't choke on files that use \r\n */
118 NL [\r?\n]
120 %array
121 %option never-interactive
125 any             return IDL_ANY;
126 Object          return IDL_OBJECT;
127 module          return IDL_MODULE;
128 raises          return IDL_RAISES;
129 readonly        return IDL_READONLY;
130 attribute       return IDL_ATTRIBUTE;
131 exception       return IDL_EXCEPTION;
132 context         return IDL_CONTEXT;
133 interface       return IDL_INTERFACE;
134 const           return IDL_CONST;
135 typedef         return IDL_TYPEDEF;
136 struct          return IDL_STRUCT;
137 enum            return IDL_ENUM;
138 string          return IDL_STRING;
139 wstring         return IDL_WSTRING;
140 sequence        return IDL_SEQUENCE;
141 union           return IDL_UNION;
142 fixed           return IDL_FIXED;
143 switch          return IDL_SWITCH;
144 case            return IDL_CASE;
145 default         return IDL_DEFAULT;
146 float           return IDL_FLOAT;
147 double          return IDL_DOUBLE;
148 long            return IDL_LONG;
149 short           return IDL_SHORT;
150 unsigned        return IDL_UNSIGNED;
151 char            return IDL_CHAR;
152 wchar           return IDL_WCHAR;
153 boolean         return IDL_BOOLEAN;
154 octet           return IDL_OCTET;
155 void            return IDL_VOID;
156 native          return IDL_NATIVE;
157 local           return IDL_LOCAL;
158 abstract        return IDL_ABSTRACT;
160 int8 {
161   if (idl_global->idl_version_ >= IDL_VERSION_4)
162     return IDL_INT8;
163   else
164     {
165       REJECT;
166     }
168 uint8 {
169   if (idl_global->idl_version_ >= IDL_VERSION_4)
170     return IDL_UINT8;
171   else
172     {
173       REJECT;
174     }
176 int16 {
177   if (idl_global->idl_version_ >= IDL_VERSION_4)
178     return IDL_INT16;
179   else
180     {
181       REJECT;
182     }
184 uint16 {
185   if (idl_global->idl_version_ >= IDL_VERSION_4)
186     return IDL_UINT16;
187   else
188     {
189       REJECT;
190     }
192 int32 {
193   if (idl_global->idl_version_ >= IDL_VERSION_4)
194     return IDL_INT32;
195   else
196     {
197       REJECT;
198     }
200 uint32 {
201   if (idl_global->idl_version_ >= IDL_VERSION_4)
202     return IDL_UINT32;
203   else
204     {
205       REJECT;
206     }
208 int64 {
209   if (idl_global->idl_version_ >= IDL_VERSION_4)
210     return IDL_INT64;
211   else
212     {
213       REJECT;
214     }
216 uint64 {
217   if (idl_global->idl_version_ >= IDL_VERSION_4)
218     return IDL_UINT64;
219   else
220     {
221       REJECT;
222     }
225 custom          return IDL_CUSTOM;
226 factory         return IDL_FACTORY;
227 private         return IDL_PRIVATE;
228 public          return IDL_PUBLIC;
229 supports        return IDL_SUPPORTS;
230 truncatable     return IDL_TRUNCATABLE;
231 valuetype       return IDL_VALUETYPE;
233 component       return IDL_COMPONENT;
234 consumes        return IDL_CONSUMES;
235 emits           return IDL_EMITS;
236 eventtype       return IDL_EVENTTYPE;
237 finder          return IDL_FINDER;
238 getraises       return IDL_GETRAISES;
239 home            return IDL_HOME;
240 import          return IDL_IMPORT;
241 multiple        return IDL_MULTIPLE;
242 primarykey      return IDL_PRIMARYKEY;
243 provides        return IDL_PROVIDES;
244 publishes       return IDL_PUBLISHES;
245 setraises       return IDL_SETRAISES;
246 typeid          return IDL_TYPEID;
247 typeprefix      return IDL_TYPEPREFIX;
248 uses            return IDL_USES;
249 manages         return IDL_MANAGES;
251 typename        return IDL_TYPENAME;
252 port            return IDL_PORT;
253 mirrorport      return IDL_MIRRORPORT;
254 porttype        return IDL_PORTTYPE;
255 connector       return IDL_CONNECTOR;
256 alias           return IDL_ALIAS;
258 TRUE            return IDL_TRUETOK;
259 FALSE           return IDL_FALSETOK;
261 inout           return IDL_INOUT;
262 in              return IDL_IN;
263 out             return IDL_OUT;
264 oneway          return IDL_ONEWAY;
266 \<\<            return IDL_LEFT_SHIFT;
267 \>\>            return IDL_RIGHT_SHIFT;
268 \:\:            {
269                   tao_yylval.strval = ACE::strnew ("::");
270                   return IDL_SCOPE_DELIMITOR;
271                 }
273 @annotation[^A-Za-z0-9_] return IDL_ANNOTATION_DECL; // Allow annotation names that start with "annotation"
274 @ return IDL_ANNOTATION_SYMBOL;
276 [a-ij-rs-zA-IJ-RS-Z_][a-ij-rs-zA-IJ-RS-Z0-9_]* {
277   // Make sure that this identifier is not a C++ keyword. If it is,
278   // prepend it with a _cxx_. Lookup in the perfect hash table for C++
279   // keyword and grab the mapping.  BTW, the reason for the odd
280   // regular expression is to handle EBCDIC, as well as ASCII.
282   TAO_IDL_CPP_Keyword_Table cpp_key_tbl;
283   const TAO_IDL_CPP_Keyword_Entry *entry = 0;
284   if (!idl_global->preserve_cpp_keywords())
285     {
286       // This check will ensure that escaped C++ keywords will be
287       // caught and prepended with '_cxx' as non-escaped keywords
288       // are now prepended with '_cxx_'.
289       const char *tmp =
290         ace_yytext[0] == '_' ? ace_yytext + 1 : ace_yytext;
292       entry =
293         cpp_key_tbl.lookup (tmp,
294                             static_cast<unsigned int> (ACE_OS::strlen (tmp)));
295     }
297   if (entry)
298     {
299       tao_yylval.strval = ACE::strnew (entry->mapping_);
300     }
301   else
302     {
303       tao_yylval.strval = ACE::strnew (ace_yytext);
304     }
306   return IDENTIFIER;
309 "-"?(([0-9]+"."[0-9]*)|("."[0-9]+))([eE][+-]?[0-9]+)?[lLfF]?      {
310                   tao_yylval.dval = idl_atof (ace_yytext);
311                   return IDL_FLOATING_PT_LITERAL;
312                 }
313 "-"?[0-9]+[eE][+-]?[0-9]+[lLfF]?  {
314                   tao_yylval.dval = idl_atof (ace_yytext);
315                   return IDL_FLOATING_PT_LITERAL;
316                 }
318 "-"?(([0-9]+"."[0-9]*)|("."?[0-9]+))[dD] {
319                   tao_yylval.fixval = ACE_CDR::Fixed::from_string (ace_yytext);
320                   return IDL_FIXED_PT_LITERAL;
321                 }
323 "-"[1-9][0-9]*  {
324                   tao_yylval.ival = idl_atoi (ace_yytext, 10);
325                   return IDL_INTEGER_LITERAL;
326                 }
327 [1-9][0-9]*     {
328                   tao_yylval.uival = idl_atoui (ace_yytext, 10);
329                   return IDL_UINTEGER_LITERAL;
330                 }
331 "-"0[xX][a-fA-F0-9]+ {
332                   tao_yylval.ival = idl_atoi (ace_yytext, 16);
333                   return IDL_INTEGER_LITERAL;
334                 }
335 0[xX][a-fA-F0-9]+ {
336                   tao_yylval.uival = idl_atoui (ace_yytext, 16);
337                   return IDL_UINTEGER_LITERAL;
338                 }
339 "-"0[0-7]*      {
340                   tao_yylval.ival = idl_atoi (ace_yytext, 8);
341                   return IDL_INTEGER_LITERAL;
342                 }
343 0[0-7]*         {
344                   tao_yylval.uival = idl_atoui (ace_yytext, 8);
345                   return IDL_UINTEGER_LITERAL;
346                 }
348 (\"([^\\\"]*|\\[ntvbrfax\\\?\'\"]|\\[0-7]{1,3})*\"[ \t]*)+ {
349                   /* Skip the quotes */
350                   char * const tmp = ace_yytext;
351                   for (size_t i = ACE_OS::strlen (tmp); i-- != 0; )
352                     {
353                       if (isspace (tmp[i]))
354                         {
355                           tmp[i] = '\0';
356                         }
357                       else
358                         {
359                           break;
360                         }
361                     }
362                   tmp[ACE_OS::strlen (tmp) - 1] = '\0';
363                   ACE_NEW_RETURN (tao_yylval.sval,
364                                   UTL_String (tmp + 1, true),
365                                   IDL_STRING_LITERAL);
366                   return IDL_STRING_LITERAL;
367                 }
368 (L\"([^\\\"]*|\\[ntvbrfax\\\?\'\"]|\\[0-7]{1,3}|\\u([0-9a-fA-F]{1,4}))*\"[ \t]*)+ {
369                   /* Skip the bookends */
370                   char * const tmp = ACE_OS::strdup (ace_yytext);
371                   for (size_t i = ACE_OS::strlen (tmp); i-- != 0; )
372                     {
373                       if (isspace (tmp[i]))
374                         {
375                           tmp[i] = '\0';
376                         }
377                       else
378                         {
379                           break;
380                         }
381                     }
382                   tmp[ACE_OS::strlen (tmp) - 1] = '\0';
383                   tao_yylval.wsval = ACE_OS::strdup (idl_wstring_escape_reader (tmp + 2));
384                   ACE_OS::free (tmp);
385                   return IDL_WSTRING_LITERAL;
386                 }
387 "'"."'"         {
388                   tao_yylval.cval = ace_yytext[1];
389                   return IDL_CHARACTER_LITERAL;
390                 }
391 "'"\\([0-7]{1,3})"'" {
392                   // octal character constant
393                   tao_yylval.cval = idl_escape_reader (ace_yytext + 1);
394                   return IDL_CHARACTER_LITERAL;
395                 }
396 "'"\\[xX]([0-9a-fA-F]{1,2})"'" {
397                   // hexadecimal character constant
398                   tao_yylval.cval = idl_escape_reader (ace_yytext + 1);
399                   return IDL_CHARACTER_LITERAL;
400                 }
401 "'"\\."'"       {
402                   tao_yylval.cval = idl_escape_reader (ace_yytext + 1);
403                   return IDL_CHARACTER_LITERAL;
404                 }
405 L"'"."'"        {
406                   // wide character constant
407                   tao_yylval.wcval = ace_yytext[2];
408                   return IDL_WCHAR_LITERAL;
409                 }
410 L"'"\\u([0-9a-fA-F]{1,4})"'" {
411                   // hexadecimal wide character constant
412                   tao_yylval.wcval = idl_wchar_escape_reader (ace_yytext + 2);
413                   return IDL_WCHAR_LITERAL;
414                 }
415 ^[ \t]*#[ \t]*pragma[ \t].*{NL} |
416 ^\?\?=[ \t]*pragma[ \t].*{NL} {/* remember pragma */
417                   idl_global->set_lineno (idl_global->lineno () + 1);
418                   idl_store_pragma (ace_yytext);
419                   break;
420                 }
421 ^[ \t]*#file[ \t].*{NL} |
422 ^\?\?=[ \t]*file[ \t].*{NL} {/* ignore file */
423                   idl_global->set_lineno(idl_global->lineno () + 1);
424                   break;
425                 }
426 ^[ \t]*#[ \t]*[0-9]*" ""\""[^\"]*"\""" "[0-9]*([ \t]*[0-9]*)*{NL} |
427 ^\?\?=[ \t]*[0-9]*" ""\""[^\"]*"\""" "[0-9]*([ \t]*[0-9]*)?{NL} {
428                   idl_parse_line_and_file (ace_yytext);
429                   break;
430                 }
431 ^[ \t]*#[ \t]*[0-9]*" ""\""[^\"]*"\""{NL} |
432 ^\?\?=[ \t]*[0-9]*" ""\""[^\"]*"\""{NL} {
433                   idl_parse_line_and_file (ace_yytext);
434                   break;
435                 }
436 ^[ \t]*#line[ \t]*[0-9]+[ \t]*("\""[^\"]*"\""([ \t]*[0-9]*([ \t]*[0-9]*)?)?)?{NL} |
437 ^\?\?=line[ \t]*[0-9]*" ""\""[^\"]*"\""{NL} {
438                   idl_parse_line_and_file (ace_yytext);
439                   break;
440                 }
441 ^[ \t]*#[ \t]*[0-9]*{NL} |
442 ^\?\?=[ \t]*[0-9]*{NL} {
443                   idl_parse_line_and_file (ace_yytext);
444                   break;
445                 }
446 ^[ \t]*#[ \t]*ident[ \t].*{NL} |
447 ^\?\?=[ \t]*ident[ \t].*{NL} {
448                   /* ignore cpp ident */
449                   idl_global->set_lineno (idl_global->lineno () + 1);
450                   break;
451                 }
452 \/\/.*{NL}      {
453                   /* ignore comments */
454                   idl_global->set_lineno(idl_global->lineno () + 1);
455                   break;
456                 }
457 "/*"            {
458                   for (;;)
459                     {
460                       char const c = yyinput ();
461                       if (c == '*')
462                         {
463                           char const next = yyinput ();
464                           if (next == '/')
465                             break;
466                           else
467                             yyunput (c, 0);
468                         }
469                       else if (c == '\n')
470                         {
471                           idl_global->set_lineno (idl_global->lineno () + 1);
472                         }
473                     }
474                   break;
475                 }
476 [ \t]*          break;
477 {NL}            {
478                   idl_global->set_lineno (idl_global->lineno () + 1);
479                   break;
480                 }
481 .               return ace_yytext[0];
484         /* subroutines */
486 static bool
487 same_file (char *path1, char *path2)
489   char fullpath1 [MAXPATHLEN + 1] = {0};
490   char fullpath2 [MAXPATHLEN + 1] = {0};
492   char *fp1 = ACE_OS::realpath (path1, fullpath1);
493   char *fp2 = ACE_OS::realpath (path2, fullpath2);
495   return
496     (fp1 == 0 || fp2 == 0)
497       ? false
498       : FE_Utils::path_cmp (fullpath1,fullpath2) == 0;
501 // Parse a #line statement generated by the C preprocessor
502 static void
503 idl_parse_line_and_file (char *buf)
505   char *r = buf;
506   char *h = 0;
507   UTL_String *nm = 0;
509   // Skip initial '#'.
510   if (*r != '#')
511     {
512       return;
513     }
514   else
515     {
516       ++r;
517     }
519   // Check to see if we're running under the screwy Microsoft scheme
520   // of putting #line num instead of #num.
522   if (ACE_OS::strncmp (r, "line", 4) == 0)
523     {
524       r += 5;
525     }
527   // Find line number.
528   while (isspace (*r))
529     {
530       ++r;
531     }
533   h = r;
535   for (; isdigit (*r); ++r)
536     {
537       continue;
538     }
540   *r++ = 0;
541   idl_global->set_lineno ((long) idl_atoui (h, 10));
543   // Find file name, if present.
544   for (; *r != '"'; ++r)
545     {
546       if (*r == '\n' || *r == '\0')
547         {
548           return;
549         }
550     }
552   h = ++r;
554   for (; *r != '"'; ++r)
555     {
556       continue;
557     }
559   *r = 0;
560   UTL_String *tmp = 0;
562   if (*h == '\0')
563     {
564       ACE_ERROR ((LM_ERROR,
565                   ACE_TEXT ("IDL: No input files\n")));
567       throw Bailout ();
568     }
569   else
570     {
571       long i;
572       long j;
574       // Put Microsoft-style pathnames into a canonical form.
575       for (i = 0, j = 0; h[j] != '\0'; i++, j++)
576         {
577           if (h[j] == '\\' && h[j + 1] == '\\')
578             {
579               j++;
580             }
582             h[i] = h[j];
583         }
585       h[i] = '\0';
586 #if defined (ACE_OPENVMS)
587       // translate this into *nix format as the OpenVMS preprocessor
588       // possibly produced VMS-style paths here.
589       char trans_path[MAXPATHLEN] = "";
590       char *temp_h = IDL_GlobalData::translateName (h, trans_path);
591       if (temp_h)
592         h = temp_h;
593       else
594         {
595           ACE_ERROR ((LM_ERROR,
596                       ACE_TEXT ("Unable to construct full file pathname\n")));
597           throw Bailout ();
598         }
599 #endif
600       ACE_NEW (tmp,
601                UTL_String (h, true));
602       idl_global->update_prefix (tmp->get_string ());
603       idl_global->set_filename (tmp);
604     }
606   UTL_String *fname = idl_global->filename ();
607   bool in_main_file = false;
609   bool is_real_filename =
610     fname->compare (idl_global->real_filename ())
611     || same_file (fname->get_string(),
612                   idl_global->real_filename ()->get_string ());
614   bool is_main_filename = false;
616   if (!is_real_filename)
617     {
618 #if defined (ACE_OPENVMS)
619       char full_path[MAXPATHLEN] = "";
620       char *full_fname = ACE_OS::realpath (fname->get_string (), full_path);
621       // I don't see the benefit of using ->compare since this is targeted at IDL identifiers
622       // not at filenames and in the case of OpenVMS (case-insensitive filesystem) gets really
623       // problematic as filenames retrieved through different mechanisms may give different
624       // casing.
625       is_main_filename = FE_Utils::path_cmp (idl_global->main_filename ()->get_string (),
626                                              full_fname) == 0;
627 #else
628       is_main_filename =
629         fname->compare (idl_global->main_filename ())
630         || same_file (fname->get_string (),
631                       idl_global->main_filename ()->get_string ());
632 #endif
633     }
635   if (is_real_filename || is_main_filename)
636     {
637       in_main_file = true;
638     }
640   idl_global->set_in_main_file (in_main_file);
642   // Strip off any command line -I prefix that may have been added
643   // by the preprocessor.
644   if (!(idl_global->in_main_file ()) && idl_global->import ())
645     {
646       ACE_NEW (nm,
647                UTL_String (
648                  FE_Utils::stripped_preproc_include (
649                    fname->get_string ()), true));
651       // This call also manages the #pragma prefix.
652       idl_global->store_include_file_name (nm);
653     }
656 // Store a #pragma line into the list of pragmas
657 static void
658 idl_store_pragma (char *buf)
660   char *sp = buf + 1;
661   int crunched = 0;
663   // Remove all the blanks between the '#' and the 'pragma'.
664   while (*sp != 'p')
665     {
666       ++sp;
667       ++crunched;
668     }
670   char *tp = buf + 1;
672   // This copies the crunched string back to the original, and
673   // also compensates for the behavior of the Sun preprocessor,
674   // which put spaces around the double colons of a non-quoted
675   // scoped name, a case which is possible in #pragma version.
676   // Also eats whitespace, which some preprocessors (for example
677   // Intel) don't automatically do.
678   while (*sp != '\n')
679     {
680       if (*sp == ' ' && (*(sp + 1) == ':' || *(sp + 1) == ' '))
681         {
682           ++crunched;
683         }
684       else if (*sp == ':' && *(sp + 1) == ' ')
685         {
686           *tp = *sp;
687           ++crunched;
688           ++sp;
689           ++tp;
690         }
691       else
692         {
693           *tp = *sp;
694           ++tp;
695         }
697       ++sp;
698     }
700   // The '\n' is still <crunched> spaces too far away, with
701   // garbage characters in between.
702   sp -= crunched;
703   *sp = '\0';
705   if (ACE_OS::strstr (buf + 8, "import") != 0)
706     {
707       idl_global->set_import (true);
708       return;
709     }
711   if (ACE_OS::strstr (buf + 8, "include") != 0)
712     {
713       idl_global->set_import (false);
714       return;
715     }
717   if (ACE_OS::strncmp (buf + 8, "prefix", 6) == 0)
718     {
719       char *new_prefix = idl_get_pragma_string (buf);
721       if (new_prefix != 0)
722         {
723           unsigned long depth = idl_global->scopes ().depth ();
725           // We replace the prefix only if there is a prefix already
726           // associated with this file, otherwise we add the prefix.
727           char *ext_id = idl_global->filename ()->get_string ();
728           ACE_Hash_Map_Entry<char *, char *> *entry = 0;
729           int const status =
730             idl_global->file_prefixes ().find (ext_id, entry);
732           if (status == 0)
733             {
734               if (ACE_OS::strcmp (entry->int_id_, "") != 0)
735                 {
736                   char *trash = 0;
737                   idl_global->pragma_prefixes ().pop (trash);
738                   delete [] trash;
739                 }
740               else if (depth == 1)
741                 {
742                   // Remove the default "" and bind the new prefix.
743                   ACE::strdelete (entry->ext_id_);
744                   ACE::strdelete (entry->int_id_);
745                   (void) idl_global->file_prefixes ().unbind (entry);
746                   (void) idl_global->file_prefixes ().bind (ACE::strnew (ext_id),
747                                                             ACE::strnew (new_prefix));
748                 }
749             }
751           UTL_Scope *top_scope = idl_global->scopes ().top ();
753           if (depth > 1)
754             {
755               top_scope->has_prefix (true);
756               ScopeAsDecl (top_scope)->prefix_scope (top_scope);
757             }
759           idl_global->pragma_prefixes ().push (new_prefix);
761           if (depth == 1)
762             {
763               idl_global->root ()->prefix (new_prefix);
764             }
766           if (idl_global->in_main_file ())
767             {
768               idl_global->root ()->set_imported (false);
769               top_scope->has_prefix (true);
770             }
772           if (status != 0)
773             {
774               (void) idl_global->file_prefixes ().bind (ACE::strnew (ext_id),
775                                                         ACE::strnew (new_prefix));
776             }
777         }
778     }
779   else if (ACE_OS::strncmp (buf + 8, "version", 7) == 0)
780     {
781       char *tmp = buf + 16;
783       while (*tmp == ' ' || *tmp == '\t')
784         {
785           ++tmp;
786         }
788       char *number = ACE_OS::strchr (tmp, ' ');
790       if (number == 0)
791         {
792           number = ACE_OS::strchr (tmp, '\t');
793         }
795       // Used later to trim the type string.
796       ptrdiff_t cutoff = number - tmp;
798       // Most likely this means there is only a version number
799       // without an identifier to apply it to.
800       if (number == 0)
801         {
802           const char *msg = "no identifier or scoped name";
803           idl_global->err ()->version_syntax_error (msg);
804           return;
805         }
807       while (*number == ' ' || *number == '\t')
808         {
809           ++number;
810         }
812       size_t len = ACE_OS::strlen (number);
814       // For some reason, the SunCC preprocessor adds a trailing space, which
815       // messes with idl_valid_version() below, so we check and remove.
816       while (number[len - 1] == ' ')
817         {
818           number[len - 1] = '\0';
819           len = ACE_OS::strlen (number);
820         }
822       // Trim the type string after trimming the number string.
823       tmp[cutoff] = '\0';
825       // This call adds a proper null terminator to tmp, so no need to
826       // do it here.
827       AST_Decl *d = idl_find_node (tmp);
829       if (d == 0)
830         {
831           return;
832         }
834       if (!idl_valid_version (number))
835         {
836           idl_global->err ()->version_number_error (number);
837           return;
838         }
840       d->version (ACE::strnew (number));
841     }
842   else if (ACE_OS::strncmp (buf + 8, "ident", 5) == 0)
843     {
844       idl_global->ident_string (buf + 8);
845     }
846   else if (ACE_OS::strncmp (buf + 8, "ID", 2) == 0)
847     {
848       char *tmp = buf + 11;
850       while (*tmp == ' ')
851         {
852           ++tmp;
853         }
855       ACE_CString work (tmp);
856       work = work.substr (0, work.find (' '));
858       AST_Decl *d = idl_find_node (work.c_str ());
860       if (d == 0)
861         {
862           return;
863         }
865       char *new_id = idl_get_pragma_string (buf);
867       if (new_id != 0)
868         {
869           if (d->typeid_set ())
870             {
871               idl_global->err ()->id_reset_error (d->repoID (),
872                                                   new_id);
873               return;
874             }
876           d->repoID (new_id);
877           d->typeid_set (true);
878         }
879     }
880   else if (ACE_OS::strncmp (buf + 8, "DCPS_DATA_TYPE", 14) == 0)
881     {
882       char *sample_type = idl_get_pragma_string (buf);
883       idl_global->add_dcps_data_type (sample_type);
885       // Delete sample_type since add_dcps_data_type() doesn't take its ownership.
886       delete [] sample_type;
887     }
888   else if (ACE_OS::strncmp (buf + 8, "DCPS_DATA_KEY", 13) == 0)
889     {
890       char *tmp = idl_get_pragma_string (buf);
892       // Split up data type and key strings
893       char *sample_type = tmp;
895       while (*tmp && !isspace (*tmp))
896         {
897           ++tmp;
898         }
900       while (isspace (*tmp))
901         {
902           *tmp = '\0';
903           tmp++;
904         }
906       char *key = tmp;
908       if (!idl_global->add_dcps_data_key (sample_type, key))
909         {
910           ACE_ERROR((LM_ERROR, "DCPS_DATA_TYPE \"%C\" not found for key \"%C\"\n",
911             sample_type, key));
912         }
914       // Delete sample_type since add_dcps_data_key() doesn't take its ownership.
915       delete [] sample_type;
916     }
917   else if (ACE_OS::strncmp (buf + 8, "DCPS_DATA_SEQUENCE_TYPE", 23) == 0)
918     {
919       char *seq_type = idl_get_pragma_string (buf);
920       idl_global->set_dcps_sequence_type (seq_type);
922       delete [] seq_type;
923     }
924   else if (ACE_OS::strncmp (buf + 8, "DCPS_SUPPORT_ZERO_COPY_READ", 27) == 0)
925     {
926       idl_global->dcps_support_zero_copy_read (true);
927     }
928   else if (ACE_OS::strncmp (buf + 8, "DCPS_GEN_ZERO_COPY_READ", 23) == 0)
929     {
930       idl_global->dcps_gen_zero_copy_read (true);
931     }
932   else if (ACE_OS::strncmp (buf + 8, "ciao lem", 8) == 0)
933     {
934       char *tmp = idl_get_pragma_string (buf);
935       idl_global->add_ciao_lem_file_names (tmp);
937       // Delete tmp since add_ciao_lem_file_names() doesn't take its ownership.
938       delete [] tmp;
939     }
940   else if (ACE_OS::strncmp (buf + 8, "ndds typesupport", 16) == 0)
941     {
942       char *tmp = idl_get_pragma_string (buf);
943       idl_global->add_ciao_rti_ts_file_names (tmp);
945       // Delete tmp since add_ciao_rti_ts_file_names() doesn't take its ownership.
946       delete [] tmp;
947     }
948   else if (ACE_OS::strncmp (buf + 8, "coredx typesupport", 18) == 0)
949     {
950       char *tmp = idl_get_pragma_string (buf);
951       idl_global->add_ciao_coredx_ts_file_names (tmp);
953       // Delete tmp since add_ciao_coredx_ts_file_names() doesn't take its ownership.
954       delete [] tmp;
955     }
956   else if (ACE_OS::strncmp (buf + 8, "opendds typesupport", 19) == 0)
957     {
958       char *tmp = idl_get_pragma_string (buf);
959       idl_global->add_ciao_oci_ts_file_names (tmp);
961       // Delete tmp since add_ciao_oci_ts_file_names() doesn't take its ownership.
962       delete [] tmp;
963     }
964   else if (ACE_OS::strncmp (buf + 8, "splice typesupport", 18) == 0)
965     {
966       char *tmp = idl_get_pragma_string (buf);
967       idl_global->add_ciao_spl_ts_file_names (tmp);
969       // Delete tmp since add_ciao_spl_ts_file_names() doesn't take its ownership.
970       delete [] tmp;
971     }
972   else if ((ACE_OS::strncmp (buf + 8, "ciao ami4ccm interface", 22) == 0) ||
973            (ACE_OS::strncmp (buf + 8, "ami4ccm interface", 17) == 0))
974     {
975       if (idl_global->in_main_file ())
976         {
977           char *tmp = idl_get_pragma_string (buf);
978           idl_global->add_ciao_ami_iface_names (tmp);
980           // Delete tmp since add_ciao_ami_iface_names() doesn't take its ownership.
981           delete [] tmp;
982         }
983     }
984   else if ((ACE_OS::strncmp (buf + 8, "ciao ami4ccm receptacle", 23) == 0) ||
985            (ACE_OS::strncmp (buf + 8, "ami4ccm receptacle", 18) == 0))
986     {
987       char *tmp = idl_get_pragma_string (buf);
989       if (idl_global->in_main_file ())
990         {
991           idl_global->add_ciao_ami_recep_names (tmp);
992         }
993       else
994         {
995           /// This is intended for the executor IDL file,
996           /// when a pragma is seen in the main file, but
997           /// it will do no harm in other cases.
998           idl_global->add_included_ami_recep_names (tmp);
999         }
1001       // Delete tmp since add_ciao_spl_ts_file_names() doesn't take its ownership.
1002       delete [] tmp;
1003     }
1004   else if ((ACE_OS::strncmp (buf + 8, "ciao ami4ccm idl", 16) == 0) ||
1005            (ACE_OS::strncmp (buf + 8, "ami4ccm idl", 11) == 0))
1006     {
1007       char *tmp = idl_get_pragma_string (buf);
1009       /// These pragmas are found in the file where the interface
1010       /// that has a AMI4CCM_* counterpart in the *A.idl file
1011       /// is declared. We add the filename to the list in all
1012       /// IDL files *except* the one where it is found, to
1013       /// eliminate a circular include of xxxC.h and xxxAC.h.
1014       if (!idl_global->in_main_file ())
1015         {
1016           idl_global->add_ciao_ami_idl_fnames (tmp);
1017         }
1019       // Delete tmp since add_ciao_ami_idl_fnames() doesn't take its ownership.
1020       delete [] tmp;
1021     }
1022   else if (ACE_OS::strncmp (buf + 8, "dds4ccm impl", 12) == 0)
1023     {
1024       char *tmp = idl_get_pragma_string (buf);
1026       idl_global->add_dds4ccm_impl_fnames (tmp);
1028       // Delete tmp since add_dds4ccm_impl_fnames() doesn't take its ownership.
1029       delete [] tmp;
1030     }
1034  * idl_atoi - Convert a string of digits into a negative integer according to base b
1035  */
1036 static ACE_CDR::LongLong
1037 idl_atoi (char *s, long b)
1039   ACE_CDR::LongLong r = 0;
1041   // Skip over the dash and possibly spaces after the dash
1042   while (*s == '-' || *s == ' ' || *s == '\t')
1043     {
1044       ++s;
1045     }
1047   if (b == 8 && *s == '0')
1048     {
1049       ++s;
1050     }
1051   else if (b == 16 && *s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))
1052     {
1053       s += 2;
1054     }
1056   for (; *s; ++s)
1057     {
1058       if (*s <= '9' && *s >= '0')
1059         {
1060           r = (r * b) + (*s - '0');
1061         }
1062       else if (b > 10 && *s <= 'f' && *s >= 'a')
1063         {
1064           r = (r * b) + (*s - 'a' + 10);
1065         }
1066       else if (b > 10 && *s <= 'F' && *s >= 'A')
1067         {
1068           r = (r * b) + (*s - 'A' + 10);
1069         }
1070       else
1071         {
1072           break;
1073         }
1074     }
1076   return -r;
1080  * idl_atoui - Convert a string of digits into an unsigned integer according to base b
1081  */
1082 static ACE_CDR::ULongLong
1083 idl_atoui (char *s, long b)
1085   ACE_CDR::ULongLong r = 0;
1087   if (b == 8 && *s == '0')
1088     {
1089       ++s;
1090     }
1091   else if (b == 16 && *s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))
1092     {
1093       s += 2;
1094     }
1096   for (; *s; ++s)
1097     {
1098       if (*s <= '9' && *s >= '0')
1099         {
1100           r = (r * b) + (*s - '0');
1101         }
1102       else if (b > 10 && *s <= 'f' && *s >= 'a')
1103         {
1104           r = (r * b) + (*s - 'a' + 10);
1105         }
1106       else if (b > 10 && *s <= 'F' && *s >= 'A')
1107         {
1108           r = (r * b) + (*s - 'A' + 10);
1109         }
1110       else
1111         {
1112           break;
1113         }
1114     }
1116   return r;
1120  * Convert a string to a float; atof doesn't seem to work, always.
1121  */
1122 static ACE_CDR::Double
1123 idl_atof (char *s)
1125   double d = 0.0;
1126   double e, k;
1127   long neg = 0, negexp = 0;
1129   if (*s == '-')
1130     {
1131       neg = 1;
1133       // Skip over the dash and possibly spaces after the dash
1134       while (*s == '-' || *s == ' ' || *s == '\t')
1135         {
1136           ++s;
1137         }
1138     }
1140   while (*s >= '0' && *s <= '9')
1141     {
1142       d = (d * 10) + *s - '0';
1143       ++s;
1144     }
1146   if (*s == '.')
1147     {
1148       ++s;
1149       e = 10;
1151       while (*s >= '0' && *s <= '9')
1152         {
1153           d += (*s - '0') / (e * 1.0);
1154           e *= 10;
1155           ++s;
1156         }
1157     }
1159   if (*s == 'e' || *s == 'E')
1160     {
1161       ++s;
1163       if (*s == '-')
1164         {
1165             negexp = 1;
1166             s++;
1167         }
1168       else if (*s == '+')
1169         {
1170           ++s;
1171         }
1173       e = 0;
1175       while (*s >= '0' && *s <= '9')
1176         {
1177           e = (e * 10) + *s - '0';
1178           ++s;
1179         }
1181       if (e > 0)
1182         {
1183           for (k = 1; e > 0; k *= 10, e--) ;
1185           if (negexp)
1186             {
1187               d /= k;
1188             }
1189           else
1190             {
1191               d *= k;
1192             }
1193         }
1194     }
1196   if (neg)
1197     {
1198       d *= -1.0;
1199     }
1201   return d;
1205  * Convert (some) escaped characters into their ascii values
1206  */
1207 static char
1208 idl_escape_reader (char *str)
1210   if (str[0] != '\\')
1211     {
1212       return str[0];
1213     }
1215   switch (str[1])
1216   {
1217     case 'n':
1218       return '\n';
1219     case 't':
1220       return '\t';
1221     case 'v':
1222       return '\v';
1223     case 'b':
1224       return '\b';
1225     case 'r':
1226       return '\r';
1227     case 'f':
1228       return '\f';
1229     case 'a':
1230       return '\a';
1231     case '\\':
1232       return '\\';
1233     case '\?':
1234       return '?';
1235     case '\'':
1236       return '\'';
1237     case '"':
1238       return '"';
1239     case 'x':
1240       {
1241         int i;
1243         // hex value
1244         for (i = 2; str[i] != '\0' && isxdigit (str[i]); ++i)
1245           {
1246             continue;
1247           }
1249         char save = str[i];
1250         str[i] = '\0';
1251         char out = (char)idl_atoui(&str[2], 16);
1252         str[i] = save;
1253         return out;
1254       }
1255       ACE_NOTREACHED (break;)
1256     default:
1257       // check for octal value
1258       if (str[1] >= '0' && str[1] <= '7')
1259         {
1260           int i;
1262           for (i = 1; str[i] >= '0' && str[i] <= '7'; ++i)
1263             {
1264               continue;
1265             }
1267           char save = str[i];
1268           str[i] = '\0';
1269           char out = (char)idl_atoui(&str[1], 8);
1270           str[i] = save;
1271           return out;
1272         }
1273       else
1274         {
1275           return str[1] - 'a';
1276         }
1277       ACE_NOTREACHED  (break;)
1278   }
1281  * Convert escaped hex digits into a wchar
1282  */
1283 static ACE_CDR::WChar
1284 idl_wchar_escape_reader (char *str)
1286   if (str[0] != '\\' || str[1] != 'u')
1287     {
1288       return 0;
1289     }
1291   int i;
1292   // get the hex digits
1293   for (i = 2; str[i] != '\0' && isxdigit (str[i]); i++)
1294     {
1295       continue;
1296     }
1297   char save = str[i];
1298   str[i] = '\0';
1299   ACE_CDR::WChar out = (ACE_CDR::WChar) idl_atoui (&str[2], 16);
1300   str[i] = save;
1301   return out;
1305  * Checks wstring for validity
1306  */
1307 static char *
1308 idl_wstring_escape_reader (char *str)
1310   return str;
1313 static char *
1314 idl_get_pragma_string (char *pragma)
1316   // Get pointers to each end of the substring between the quotes.
1317   const char *firstquote = ACE_OS::strchr (pragma, '"');
1319   if (firstquote == 0)
1320     {
1321       idl_global->err ()->syntax_error (
1322           IDL_GlobalData::PS_PragmaPrefixSyntax
1323         );
1325       return 0;
1326     }
1328   const char *start = firstquote + 1;
1329   const char *end = ACE_OS::strchr (start, '"');
1331   if (end == 0)
1332     {
1333       idl_global->err ()->syntax_error (
1334           IDL_GlobalData::PS_PragmaPrefixSyntax
1335         );
1337       return 0;
1338     }
1340   int len = static_cast<int> (end - start);
1341   char *retval = 0;
1343   ACE_NEW_RETURN (retval,
1344                   char[len + 1],
1345                   0);
1347   ACE_OS::strncpy (retval,
1348                    start,
1349                    len);
1351   retval[len] = '\0';
1352   return retval;
1355 static bool
1356 idl_valid_version (char *s)
1358   // Nothing preceding decimal point.
1359   if (*s == '.')
1360     {
1361       return 0;
1362     }
1364   char *minor = ACE_OS::strchr (s, '.');
1365   int i;
1367   if (minor == 0)
1368     {
1369       // No decimal point.
1370       return 0;
1371     }
1373   if (*(minor + 1) == '\0')
1374     {
1375       // Nothing following decimal point.
1376       return 0;
1377     }
1379   char *tmp = minor + 1;
1381   for (i = 0; tmp[i] != '\0'; ++i)
1382     {
1383       if (!isdigit (tmp[i]))
1384         {
1385           return 0;
1386         }
1387     }
1389   ptrdiff_t const len = minor - s;
1391   for (i = 0; i < len; ++i)
1392     {
1393       if (!isdigit (s[i]))
1394         {
1395           return 0;
1396         }
1397     }
1399   // Major and minor version numbers must be unsigned shorts.
1400   if (ACE_OS::atoi (minor + 1) > ACE_UINT16_MAX
1401       || ACE_OS::atoi (s) > ACE_UINT16_MAX)
1402     {
1403       return 0;
1404     }
1406   return 1;
1409 static AST_Decl *
1410 idl_find_node (const char *s)
1412   UTL_ScopedName * node = FE_Utils::string_to_scoped_name (s);
1413   AST_Decl * d = 0;
1415   if (node != 0)
1416     {
1417       d = idl_global->scopes ().top_non_null ()->lookup_by_name (node);
1419       if (d == 0)
1420         {
1421           idl_global->err ()->lookup_error (node);
1422         }
1424       node->destroy ();
1425       delete node;
1426     }
1428   return d;