Merge pull request #2309 from mitza-oci/warnings
[ACE_TAO.git] / TAO / TAO_IDL / fe / idl.ll
blob32a2d9b4467f1cb30f70c94a12c7b844342c821c
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
115 #define IDL4_KEYWORD(TOKEN_NAME) if (idl_global->idl_version_ >= IDL_VERSION_4) return TOKEN_NAME;
119 /* SO we don't choke on files that use \r\n */
120 NL [\r?\n]
122 %array
123 %option never-interactive
127 any             return IDL_ANY;
128 Object          return IDL_OBJECT;
129 module          return IDL_MODULE;
130 raises          return IDL_RAISES;
131 readonly        return IDL_READONLY;
132 attribute       return IDL_ATTRIBUTE;
133 exception       return IDL_EXCEPTION;
134 context         return IDL_CONTEXT;
135 interface       return IDL_INTERFACE;
136 const           return IDL_CONST;
137 typedef         return IDL_TYPEDEF;
138 struct          return IDL_STRUCT;
139 enum            return IDL_ENUM;
140 string          return IDL_STRING;
141 wstring         return IDL_WSTRING;
142 sequence        return IDL_SEQUENCE;
143 union           return IDL_UNION;
144 fixed           return IDL_FIXED;
145 switch          return IDL_SWITCH;
146 case            return IDL_CASE;
147 default         return IDL_DEFAULT;
148 float           return IDL_FLOAT;
149 double          return IDL_DOUBLE;
150 long            return IDL_LONG;
151 short           return IDL_SHORT;
152 unsigned        return IDL_UNSIGNED;
153 char            return IDL_CHAR;
154 wchar           return IDL_WCHAR;
155 boolean         return IDL_BOOLEAN;
156 octet           return IDL_OCTET;
157 void            return IDL_VOID;
158 native          return IDL_NATIVE;
159 local           return IDL_LOCAL;
160 abstract        return IDL_ABSTRACT;
162 custom          return IDL_CUSTOM;
163 factory         return IDL_FACTORY;
164 private         return IDL_PRIVATE;
165 public          return IDL_PUBLIC;
166 supports        return IDL_SUPPORTS;
167 truncatable     return IDL_TRUNCATABLE;
168 valuetype       return IDL_VALUETYPE;
170 component       return IDL_COMPONENT;
171 consumes        return IDL_CONSUMES;
172 emits           return IDL_EMITS;
173 eventtype       return IDL_EVENTTYPE;
174 finder          return IDL_FINDER;
175 getraises       return IDL_GETRAISES;
176 home            return IDL_HOME;
177 import          return IDL_IMPORT;
178 multiple        return IDL_MULTIPLE;
179 primarykey      return IDL_PRIMARYKEY;
180 provides        return IDL_PROVIDES;
181 publishes       return IDL_PUBLISHES;
182 setraises       return IDL_SETRAISES;
183 typeid          return IDL_TYPEID;
184 typeprefix      return IDL_TYPEPREFIX;
185 uses            return IDL_USES;
186 manages         return IDL_MANAGES;
188 typename        return IDL_TYPENAME;
189 port            return IDL_PORT;
190 mirrorport      return IDL_MIRRORPORT;
191 porttype        return IDL_PORTTYPE;
192 connector       return IDL_CONNECTOR;
193 alias           return IDL_ALIAS;
195 TRUE            return IDL_TRUETOK;
196 FALSE           return IDL_FALSETOK;
198 inout           return IDL_INOUT;
199 in              return IDL_IN;
200 out             return IDL_OUT;
201 oneway          return IDL_ONEWAY;
203 \<\<            return IDL_LEFT_SHIFT;
204 \>\>            return IDL_RIGHT_SHIFT;
205 \:\:            {
206                   tao_yylval.strval = ACE::strnew ("::");
207                   return IDL_SCOPE_DELIMITOR;
208                 }
210 @annotation[^A-Za-z0-9_] return IDL_ANNOTATION_DECL; // Allow annotation names that start with "annotation"
211 @ return IDL_ANNOTATION_SYMBOL;
213 int8 IDL4_KEYWORD(IDL_INT8); REJECT;
214 uint8 IDL4_KEYWORD(IDL_UINT8); REJECT;
215 int16 IDL4_KEYWORD(IDL_INT16); REJECT;
216 uint16 IDL4_KEYWORD(IDL_UINT16); REJECT;
217 int32 IDL4_KEYWORD(IDL_INT32); REJECT;
218 uint32 IDL4_KEYWORD(IDL_UINT32); REJECT;
219 int64 IDL4_KEYWORD(IDL_INT64); REJECT;
220 uint64 IDL4_KEYWORD(IDL_UINT64); REJECT;
222 bitfield IDL4_KEYWORD(IDL_BITFIELD); REJECT;
223 bitmask IDL4_KEYWORD(IDL_BITMASK); REJECT;
224 bitset IDL4_KEYWORD(IDL_BITSET); REJECT;
225 map IDL4_KEYWORD(IDL_MAP); REJECT;
227 [a-ij-rs-zA-IJ-RS-Z_][a-ij-rs-zA-IJ-RS-Z0-9_]* {
228   // Make sure that this identifier is not a C++ keyword. If it is,
229   // prepend it with a _cxx_. Lookup in the perfect hash table for C++
230   // keyword and grab the mapping.  BTW, the reason for the odd
231   // regular expression is to handle EBCDIC, as well as ASCII.
233   TAO_IDL_CPP_Keyword_Table cpp_key_tbl;
234   const TAO_IDL_CPP_Keyword_Entry *entry = 0;
235   if (!idl_global->preserve_cpp_keywords())
236     {
237       // This check will ensure that escaped C++ keywords will be
238       // caught and prepended with '_cxx' as non-escaped keywords
239       // are now prepended with '_cxx_'.
240       const char *tmp =
241         ace_yytext[0] == '_' ? ace_yytext + 1 : ace_yytext;
243       entry =
244         cpp_key_tbl.lookup (tmp,
245                             static_cast<unsigned int> (ACE_OS::strlen (tmp)));
246     }
248   if (entry)
249     {
250       tao_yylval.strval = ACE::strnew (entry->mapping_);
251     }
252   else
253     {
254       tao_yylval.strval = ACE::strnew (ace_yytext);
255     }
257   return IDENTIFIER;
260 "-"?(([0-9]+"."[0-9]*)|("."[0-9]+))([eE][+-]?[0-9]+)?[lLfF]?      {
261                   tao_yylval.dval = idl_atof (ace_yytext);
262                   return IDL_FLOATING_PT_LITERAL;
263                 }
264 "-"?[0-9]+[eE][+-]?[0-9]+[lLfF]?  {
265                   tao_yylval.dval = idl_atof (ace_yytext);
266                   return IDL_FLOATING_PT_LITERAL;
267                 }
269 "-"?(([0-9]+"."[0-9]*)|("."?[0-9]+))[dD] {
270                   tao_yylval.fixval = ACE_CDR::Fixed::from_string (ace_yytext);
271                   return IDL_FIXED_PT_LITERAL;
272                 }
274 "-"[1-9][0-9]*  {
275                   tao_yylval.ival = idl_atoi (ace_yytext, 10);
276                   return IDL_INTEGER_LITERAL;
277                 }
278 [1-9][0-9]*     {
279                   tao_yylval.uival = idl_atoui (ace_yytext, 10);
280                   return IDL_UINTEGER_LITERAL;
281                 }
282 "-"0[xX][a-fA-F0-9]+ {
283                   tao_yylval.ival = idl_atoi (ace_yytext, 16);
284                   return IDL_INTEGER_LITERAL;
285                 }
286 0[xX][a-fA-F0-9]+ {
287                   tao_yylval.uival = idl_atoui (ace_yytext, 16);
288                   return IDL_UINTEGER_LITERAL;
289                 }
290 "-"0[0-7]*      {
291                   tao_yylval.ival = idl_atoi (ace_yytext, 8);
292                   return IDL_INTEGER_LITERAL;
293                 }
294 0[0-7]*         {
295                   tao_yylval.uival = idl_atoui (ace_yytext, 8);
296                   return IDL_UINTEGER_LITERAL;
297                 }
299 (\"([^\\\"]*|\\[ntvbrfax\\\?\'\"]|\\[0-7]{1,3})*\"[ \t]*)+ {
300                   /* Skip the quotes */
301                   char * const tmp = ace_yytext;
302                   for (size_t i = ACE_OS::strlen (tmp); i-- != 0; )
303                     {
304                       if (isspace (tmp[i]))
305                         {
306                           tmp[i] = '\0';
307                         }
308                       else
309                         {
310                           break;
311                         }
312                     }
313                   tmp[ACE_OS::strlen (tmp) - 1] = '\0';
314                   ACE_NEW_RETURN (tao_yylval.sval,
315                                   UTL_String (tmp + 1, true),
316                                   IDL_STRING_LITERAL);
317                   return IDL_STRING_LITERAL;
318                 }
319 (L\"([^\\\"]*|\\[ntvbrfax\\\?\'\"]|\\[0-7]{1,3}|\\u([0-9a-fA-F]{1,4}))*\"[ \t]*)+ {
320                   /* Skip the bookends */
321                   char * const tmp = ACE_OS::strdup (ace_yytext);
322                   for (size_t i = ACE_OS::strlen (tmp); i-- != 0; )
323                     {
324                       if (isspace (tmp[i]))
325                         {
326                           tmp[i] = '\0';
327                         }
328                       else
329                         {
330                           break;
331                         }
332                     }
333                   tmp[ACE_OS::strlen (tmp) - 1] = '\0';
334                   tao_yylval.wsval = ACE_OS::strdup (idl_wstring_escape_reader (tmp + 2));
335                   ACE_OS::free (tmp);
336                   return IDL_WSTRING_LITERAL;
337                 }
338 "'"."'"         {
339                   tao_yylval.cval = ace_yytext[1];
340                   return IDL_CHARACTER_LITERAL;
341                 }
342 "'"\\([0-7]{1,3})"'" {
343                   // octal character constant
344                   tao_yylval.cval = idl_escape_reader (ace_yytext + 1);
345                   return IDL_CHARACTER_LITERAL;
346                 }
347 "'"\\[xX]([0-9a-fA-F]{1,2})"'" {
348                   // hexadecimal character constant
349                   tao_yylval.cval = idl_escape_reader (ace_yytext + 1);
350                   return IDL_CHARACTER_LITERAL;
351                 }
352 "'"\\."'"       {
353                   tao_yylval.cval = idl_escape_reader (ace_yytext + 1);
354                   return IDL_CHARACTER_LITERAL;
355                 }
356 L"'"."'"        {
357                   // wide character constant
358                   tao_yylval.wcval = ace_yytext[2];
359                   return IDL_WCHAR_LITERAL;
360                 }
361 L"'"\\u([0-9a-fA-F]{1,4})"'" {
362                   // hexadecimal wide character constant
363                   tao_yylval.wcval = idl_wchar_escape_reader (ace_yytext + 2);
364                   return IDL_WCHAR_LITERAL;
365                 }
366 ^[ \t]*#[ \t]*pragma[ \t].*{NL} |
367 ^\?\?=[ \t]*pragma[ \t].*{NL} {/* remember pragma */
368                   idl_global->set_lineno (idl_global->lineno () + 1);
369                   idl_store_pragma (ace_yytext);
370                   break;
371                 }
372 ^[ \t]*#file[ \t].*{NL} |
373 ^\?\?=[ \t]*file[ \t].*{NL} {/* ignore file */
374                   idl_global->set_lineno(idl_global->lineno () + 1);
375                   break;
376                 }
377 ^[ \t]*#[ \t]*[0-9]*" ""\""[^\"]*"\""" "[0-9]*([ \t]*[0-9]*)*{NL} |
378 ^\?\?=[ \t]*[0-9]*" ""\""[^\"]*"\""" "[0-9]*([ \t]*[0-9]*)?{NL} {
379                   idl_parse_line_and_file (ace_yytext);
380                   break;
381                 }
382 ^[ \t]*#[ \t]*[0-9]*" ""\""[^\"]*"\""{NL} |
383 ^\?\?=[ \t]*[0-9]*" ""\""[^\"]*"\""{NL} {
384                   idl_parse_line_and_file (ace_yytext);
385                   break;
386                 }
387 ^[ \t]*#line[ \t]*[0-9]+[ \t]*("\""[^\"]*"\""([ \t]*[0-9]*([ \t]*[0-9]*)?)?)?{NL} |
388 ^\?\?=line[ \t]*[0-9]*" ""\""[^\"]*"\""{NL} {
389                   idl_parse_line_and_file (ace_yytext);
390                   break;
391                 }
392 ^[ \t]*#[ \t]*[0-9]*{NL} |
393 ^\?\?=[ \t]*[0-9]*{NL} {
394                   idl_parse_line_and_file (ace_yytext);
395                   break;
396                 }
397 ^[ \t]*#[ \t]*ident[ \t].*{NL} |
398 ^\?\?=[ \t]*ident[ \t].*{NL} {
399                   /* ignore cpp ident */
400                   idl_global->set_lineno (idl_global->lineno () + 1);
401                   break;
402                 }
403 \/\/.*{NL}      {
404                   /* ignore comments */
405                   idl_global->set_lineno(idl_global->lineno () + 1);
406                   break;
407                 }
408 "/*"            {
409                   for (;;)
410                     {
411                       char const c = yyinput ();
412                       if (c == '*')
413                         {
414                           char const next = yyinput ();
415                           if (next == '/')
416                             break;
417                           else
418                             yyunput (c, 0);
419                         }
420                       else if (c == '\n')
421                         {
422                           idl_global->set_lineno (idl_global->lineno () + 1);
423                         }
424                     }
425                   break;
426                 }
427 [ \t]*          break;
428 {NL}            {
429                   idl_global->set_lineno (idl_global->lineno () + 1);
430                   break;
431                 }
432 .               return ace_yytext[0];
435         /* subroutines */
437 static bool
438 same_file (char *path1, char *path2)
440   char fullpath1 [MAXPATHLEN + 1] = {0};
441   char fullpath2 [MAXPATHLEN + 1] = {0};
443   char *fp1 = ACE_OS::realpath (path1, fullpath1);
444   char *fp2 = ACE_OS::realpath (path2, fullpath2);
446   return
447     (fp1 == 0 || fp2 == 0)
448       ? false
449       : FE_Utils::path_cmp (fullpath1,fullpath2) == 0;
452 // Parse a #line statement generated by the C preprocessor
453 static void
454 idl_parse_line_and_file (char *buf)
456   char *r = buf;
457   char *h = 0;
458   UTL_String *nm = 0;
460   // Skip initial '#'.
461   if (*r != '#')
462     {
463       return;
464     }
465   else
466     {
467       ++r;
468     }
470   // Check to see if we're running under the screwy Microsoft scheme
471   // of putting #line num instead of #num.
473   if (ACE_OS::strncmp (r, "line", 4) == 0)
474     {
475       r += 5;
476     }
478   // Find line number.
479   while (isspace (*r))
480     {
481       ++r;
482     }
484   h = r;
486   for (; isdigit (*r); ++r)
487     {
488       continue;
489     }
491   *r++ = 0;
492   idl_global->set_lineno ((long) idl_atoui (h, 10));
494   // Find file name, if present.
495   for (; *r != '"'; ++r)
496     {
497       if (*r == '\n' || *r == '\0')
498         {
499           return;
500         }
501     }
503   h = ++r;
505   for (; *r != '"'; ++r)
506     {
507       continue;
508     }
510   *r = 0;
511   UTL_String *tmp = 0;
513   if (*h == '\0')
514     {
515       ACE_ERROR ((LM_ERROR,
516                   ACE_TEXT ("IDL: No input files\n")));
518       throw Bailout ();
519     }
520   else
521     {
522       long i;
523       long j;
525       // Put Microsoft-style pathnames into a canonical form.
526       for (i = 0, j = 0; h[j] != '\0'; i++, j++)
527         {
528           if (h[j] == '\\' && h[j + 1] == '\\')
529             {
530               j++;
531             }
533             h[i] = h[j];
534         }
536       h[i] = '\0';
537       ACE_NEW (tmp,
538                UTL_String (h, true));
539       idl_global->update_prefix (tmp->get_string ());
540       idl_global->set_filename (tmp);
541     }
543   UTL_String *fname = idl_global->filename ();
544   bool in_main_file = false;
546   bool is_real_filename =
547     fname->compare (idl_global->real_filename ())
548     || same_file (fname->get_string(),
549                   idl_global->real_filename ()->get_string ());
551   bool is_main_filename = false;
553   if (!is_real_filename)
554     {
555       is_main_filename =
556         fname->compare (idl_global->main_filename ())
557         || same_file (fname->get_string (),
558                       idl_global->main_filename ()->get_string ());
559     }
561   if (is_real_filename || is_main_filename)
562     {
563       in_main_file = true;
564     }
566   idl_global->set_in_main_file (in_main_file);
568   // Strip off any command line -I prefix that may have been added
569   // by the preprocessor.
570   if (!(idl_global->in_main_file ()) && idl_global->import ())
571     {
572       ACE_NEW (nm,
573                UTL_String (
574                  FE_Utils::stripped_preproc_include (
575                    fname->get_string ()), true));
577       // This call also manages the #pragma prefix.
578       idl_global->store_include_file_name (nm);
579     }
582 // Store a #pragma line into the list of pragmas
583 static void
584 idl_store_pragma (char *buf)
586   char *sp = buf + 1;
587   int crunched = 0;
589   // Remove all the blanks between the '#' and the 'pragma'.
590   while (*sp != 'p')
591     {
592       ++sp;
593       ++crunched;
594     }
596   char *tp = buf + 1;
598   // This copies the crunched string back to the original, and
599   // also compensates for the behavior of the Sun preprocessor,
600   // which put spaces around the double colons of a non-quoted
601   // scoped name, a case which is possible in #pragma version.
602   // Also eats whitespace, which some preprocessors (for example
603   // Intel) don't automatically do.
604   while (*sp != '\n')
605     {
606       if (*sp == ' ' && (*(sp + 1) == ':' || *(sp + 1) == ' '))
607         {
608           ++crunched;
609         }
610       else if (*sp == ':' && *(sp + 1) == ' ')
611         {
612           *tp = *sp;
613           ++crunched;
614           ++sp;
615           ++tp;
616         }
617       else
618         {
619           *tp = *sp;
620           ++tp;
621         }
623       ++sp;
624     }
626   // The '\n' is still <crunched> spaces too far away, with
627   // garbage characters in between.
628   sp -= crunched;
629   *sp = '\0';
631   if (ACE_OS::strstr (buf + 8, "import") != 0)
632     {
633       idl_global->set_import (true);
634       return;
635     }
637   if (ACE_OS::strstr (buf + 8, "include") != 0)
638     {
639       idl_global->set_import (false);
640       return;
641     }
643   if (ACE_OS::strncmp (buf + 8, "prefix", 6) == 0)
644     {
645       char *new_prefix = idl_get_pragma_string (buf);
647       if (new_prefix != 0)
648         {
649           unsigned long depth = idl_global->scopes ().depth ();
651           // We replace the prefix only if there is a prefix already
652           // associated with this file, otherwise we add the prefix.
653           char *ext_id = idl_global->filename ()->get_string ();
654           ACE_Hash_Map_Entry<char *, char *> *entry = 0;
655           int const status =
656             idl_global->file_prefixes ().find (ext_id, entry);
658           if (status == 0)
659             {
660               if (ACE_OS::strcmp (entry->int_id_, "") != 0)
661                 {
662                   char *trash = 0;
663                   idl_global->pragma_prefixes ().pop (trash);
664                   delete [] trash;
665                 }
666               else if (depth == 1)
667                 {
668                   // Remove the default "" and bind the new prefix.
669                   ACE::strdelete (entry->ext_id_);
670                   ACE::strdelete (entry->int_id_);
671                   (void) idl_global->file_prefixes ().unbind (entry);
672                   (void) idl_global->file_prefixes ().bind (ACE::strnew (ext_id),
673                                                             ACE::strnew (new_prefix));
674                 }
675             }
677           UTL_Scope *top_scope = idl_global->scopes ().top ();
679           if (depth > 1)
680             {
681               top_scope->has_prefix (true);
682               ScopeAsDecl (top_scope)->prefix_scope (top_scope);
683             }
685           idl_global->pragma_prefixes ().push (new_prefix);
687           if (depth == 1)
688             {
689               idl_global->root ()->prefix (new_prefix);
690             }
692           if (idl_global->in_main_file ())
693             {
694               idl_global->root ()->set_imported (false);
695               top_scope->has_prefix (true);
696             }
698           if (status != 0)
699             {
700               (void) idl_global->file_prefixes ().bind (ACE::strnew (ext_id),
701                                                         ACE::strnew (new_prefix));
702             }
703         }
704     }
705   else if (ACE_OS::strncmp (buf + 8, "version", 7) == 0)
706     {
707       char *tmp = buf + 16;
709       while (*tmp == ' ' || *tmp == '\t')
710         {
711           ++tmp;
712         }
714       char *number = ACE_OS::strchr (tmp, ' ');
716       if (number == 0)
717         {
718           number = ACE_OS::strchr (tmp, '\t');
719         }
721       // Used later to trim the type string.
722       ptrdiff_t cutoff = number - tmp;
724       // Most likely this means there is only a version number
725       // without an identifier to apply it to.
726       if (number == 0)
727         {
728           const char *msg = "no identifier or scoped name";
729           idl_global->err ()->version_syntax_error (msg);
730           return;
731         }
733       while (*number == ' ' || *number == '\t')
734         {
735           ++number;
736         }
738       size_t len = ACE_OS::strlen (number);
740       // For some reason, the SunCC preprocessor adds a trailing space, which
741       // messes with idl_valid_version() below, so we check and remove.
742       while (number[len - 1] == ' ')
743         {
744           number[len - 1] = '\0';
745           len = ACE_OS::strlen (number);
746         }
748       // Trim the type string after trimming the number string.
749       tmp[cutoff] = '\0';
751       // This call adds a proper null terminator to tmp, so no need to
752       // do it here.
753       AST_Decl *d = idl_find_node (tmp);
755       if (d == 0)
756         {
757           return;
758         }
760       if (!idl_valid_version (number))
761         {
762           idl_global->err ()->version_number_error (number);
763           return;
764         }
766       d->version (ACE::strnew (number));
767     }
768   else if (ACE_OS::strncmp (buf + 8, "ident", 5) == 0)
769     {
770       idl_global->ident_string (buf + 8);
771     }
772   else if (ACE_OS::strncmp (buf + 8, "ID", 2) == 0)
773     {
774       char *tmp = buf + 11;
776       while (*tmp == ' ')
777         {
778           ++tmp;
779         }
781       ACE_CString work (tmp);
782       work = work.substr (0, work.find (' '));
784       AST_Decl *d = idl_find_node (work.c_str ());
786       if (d == 0)
787         {
788           return;
789         }
791       char *new_id = idl_get_pragma_string (buf);
793       if (new_id != 0)
794         {
795           if (d->typeid_set ())
796             {
797               idl_global->err ()->id_reset_error (d->repoID (),
798                                                   new_id);
799               return;
800             }
802           d->repoID (new_id);
803           d->typeid_set (true);
804         }
805     }
806   else if (ACE_OS::strncmp (buf + 8, "DCPS_DATA_TYPE", 14) == 0)
807     {
808       char *sample_type = idl_get_pragma_string (buf);
809       idl_global->add_dcps_data_type (sample_type);
811       // Delete sample_type since add_dcps_data_type() doesn't take its ownership.
812       delete [] sample_type;
813     }
814   else if (ACE_OS::strncmp (buf + 8, "DCPS_DATA_KEY", 13) == 0)
815     {
816       char *tmp = idl_get_pragma_string (buf);
818       // Split up data type and key strings
819       char *sample_type = tmp;
821       while (*tmp && !isspace (*tmp))
822         {
823           ++tmp;
824         }
826       while (isspace (*tmp))
827         {
828           *tmp = '\0';
829           tmp++;
830         }
832       char *key = tmp;
834       if (!idl_global->add_dcps_data_key (sample_type, key))
835         {
836           ACE_ERROR((LM_ERROR, "DCPS_DATA_TYPE \"%C\" not found for key \"%C\"\n",
837             sample_type, key));
838         }
840       // Delete sample_type since add_dcps_data_key() doesn't take its ownership.
841       delete [] sample_type;
842     }
843   else if (ACE_OS::strncmp (buf + 8, "DCPS_DATA_SEQUENCE_TYPE", 23) == 0)
844     {
845       char *seq_type = idl_get_pragma_string (buf);
846       idl_global->set_dcps_sequence_type (seq_type);
848       delete [] seq_type;
849     }
850   else if (ACE_OS::strncmp (buf + 8, "DCPS_SUPPORT_ZERO_COPY_READ", 27) == 0)
851     {
852       idl_global->dcps_support_zero_copy_read (true);
853     }
854   else if (ACE_OS::strncmp (buf + 8, "DCPS_GEN_ZERO_COPY_READ", 23) == 0)
855     {
856       idl_global->dcps_gen_zero_copy_read (true);
857     }
858   else if (ACE_OS::strncmp (buf + 8, "ciao lem", 8) == 0)
859     {
860       char *tmp = idl_get_pragma_string (buf);
861       idl_global->add_ciao_lem_file_names (tmp);
863       // Delete tmp since add_ciao_lem_file_names() doesn't take its ownership.
864       delete [] tmp;
865     }
866   else if (ACE_OS::strncmp (buf + 8, "ndds typesupport", 16) == 0)
867     {
868       char *tmp = idl_get_pragma_string (buf);
869       idl_global->add_ciao_rti_ts_file_names (tmp);
871       // Delete tmp since add_ciao_rti_ts_file_names() doesn't take its ownership.
872       delete [] tmp;
873     }
874   else if (ACE_OS::strncmp (buf + 8, "coredx typesupport", 18) == 0)
875     {
876       char *tmp = idl_get_pragma_string (buf);
877       idl_global->add_ciao_coredx_ts_file_names (tmp);
879       // Delete tmp since add_ciao_coredx_ts_file_names() doesn't take its ownership.
880       delete [] tmp;
881     }
882   else if (ACE_OS::strncmp (buf + 8, "opendds typesupport", 19) == 0)
883     {
884       char *tmp = idl_get_pragma_string (buf);
885       idl_global->add_ciao_oci_ts_file_names (tmp);
887       // Delete tmp since add_ciao_oci_ts_file_names() doesn't take its ownership.
888       delete [] tmp;
889     }
890   else if (ACE_OS::strncmp (buf + 8, "splice typesupport", 18) == 0)
891     {
892       char *tmp = idl_get_pragma_string (buf);
893       idl_global->add_ciao_spl_ts_file_names (tmp);
895       // Delete tmp since add_ciao_spl_ts_file_names() doesn't take its ownership.
896       delete [] tmp;
897     }
898   else if ((ACE_OS::strncmp (buf + 8, "ciao ami4ccm interface", 22) == 0) ||
899            (ACE_OS::strncmp (buf + 8, "ami4ccm interface", 17) == 0))
900     {
901       if (idl_global->in_main_file ())
902         {
903           char *tmp = idl_get_pragma_string (buf);
904           idl_global->add_ciao_ami_iface_names (tmp);
906           // Delete tmp since add_ciao_ami_iface_names() doesn't take its ownership.
907           delete [] tmp;
908         }
909     }
910   else if ((ACE_OS::strncmp (buf + 8, "ciao ami4ccm receptacle", 23) == 0) ||
911            (ACE_OS::strncmp (buf + 8, "ami4ccm receptacle", 18) == 0))
912     {
913       char *tmp = idl_get_pragma_string (buf);
915       if (idl_global->in_main_file ())
916         {
917           idl_global->add_ciao_ami_recep_names (tmp);
918         }
919       else
920         {
921           /// This is intended for the executor IDL file,
922           /// when a pragma is seen in the main file, but
923           /// it will do no harm in other cases.
924           idl_global->add_included_ami_recep_names (tmp);
925         }
927       // Delete tmp since add_ciao_spl_ts_file_names() doesn't take its ownership.
928       delete [] tmp;
929     }
930   else if ((ACE_OS::strncmp (buf + 8, "ciao ami4ccm idl", 16) == 0) ||
931            (ACE_OS::strncmp (buf + 8, "ami4ccm idl", 11) == 0))
932     {
933       char *tmp = idl_get_pragma_string (buf);
935       /// These pragmas are found in the file where the interface
936       /// that has a AMI4CCM_* counterpart in the *A.idl file
937       /// is declared. We add the filename to the list in all
938       /// IDL files *except* the one where it is found, to
939       /// eliminate a circular include of xxxC.h and xxxAC.h.
940       if (!idl_global->in_main_file ())
941         {
942           idl_global->add_ciao_ami_idl_fnames (tmp);
943         }
945       // Delete tmp since add_ciao_ami_idl_fnames() doesn't take its ownership.
946       delete [] tmp;
947     }
948   else if (ACE_OS::strncmp (buf + 8, "dds4ccm impl", 12) == 0)
949     {
950       char *tmp = idl_get_pragma_string (buf);
952       idl_global->add_dds4ccm_impl_fnames (tmp);
954       // Delete tmp since add_dds4ccm_impl_fnames() doesn't take its ownership.
955       delete [] tmp;
956     }
960  * idl_atoi - Convert a string of digits into a negative integer according to base b
961  */
962 static ACE_CDR::LongLong
963 idl_atoi (char *s, long b)
965   ACE_CDR::LongLong r = 0;
967   // Skip over the dash and possibly spaces after the dash
968   while (*s == '-' || *s == ' ' || *s == '\t')
969     {
970       ++s;
971     }
973   if (b == 8 && *s == '0')
974     {
975       ++s;
976     }
977   else if (b == 16 && *s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))
978     {
979       s += 2;
980     }
982   for (; *s; ++s)
983     {
984       if (*s <= '9' && *s >= '0')
985         {
986           r = (r * b) + (*s - '0');
987         }
988       else if (b > 10 && *s <= 'f' && *s >= 'a')
989         {
990           r = (r * b) + (*s - 'a' + 10);
991         }
992       else if (b > 10 && *s <= 'F' && *s >= 'A')
993         {
994           r = (r * b) + (*s - 'A' + 10);
995         }
996       else
997         {
998           break;
999         }
1000     }
1002   return -r;
1006  * idl_atoui - Convert a string of digits into an unsigned integer according to base b
1007  */
1008 static ACE_CDR::ULongLong
1009 idl_atoui (char *s, long b)
1011   ACE_CDR::ULongLong r = 0;
1013   if (b == 8 && *s == '0')
1014     {
1015       ++s;
1016     }
1017   else if (b == 16 && *s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))
1018     {
1019       s += 2;
1020     }
1022   for (; *s; ++s)
1023     {
1024       if (*s <= '9' && *s >= '0')
1025         {
1026           r = (r * b) + (*s - '0');
1027         }
1028       else if (b > 10 && *s <= 'f' && *s >= 'a')
1029         {
1030           r = (r * b) + (*s - 'a' + 10);
1031         }
1032       else if (b > 10 && *s <= 'F' && *s >= 'A')
1033         {
1034           r = (r * b) + (*s - 'A' + 10);
1035         }
1036       else
1037         {
1038           break;
1039         }
1040     }
1042   return r;
1046  * Convert a string to a float; atof doesn't seem to work, always.
1047  */
1048 static ACE_CDR::Double
1049 idl_atof (char *s)
1051   double d = 0.0;
1052   double e, k;
1053   long neg = 0, negexp = 0;
1055   if (*s == '-')
1056     {
1057       neg = 1;
1059       // Skip over the dash and possibly spaces after the dash
1060       while (*s == '-' || *s == ' ' || *s == '\t')
1061         {
1062           ++s;
1063         }
1064     }
1066   while (*s >= '0' && *s <= '9')
1067     {
1068       d = (d * 10) + *s - '0';
1069       ++s;
1070     }
1072   if (*s == '.')
1073     {
1074       ++s;
1075       e = 10;
1077       while (*s >= '0' && *s <= '9')
1078         {
1079           d += (*s - '0') / (e * 1.0);
1080           e *= 10;
1081           ++s;
1082         }
1083     }
1085   if (*s == 'e' || *s == 'E')
1086     {
1087       ++s;
1089       if (*s == '-')
1090         {
1091             negexp = 1;
1092             s++;
1093         }
1094       else if (*s == '+')
1095         {
1096           ++s;
1097         }
1099       e = 0;
1101       while (*s >= '0' && *s <= '9')
1102         {
1103           e = (e * 10) + *s - '0';
1104           ++s;
1105         }
1107       if (e > 0)
1108         {
1109           for (k = 1; e > 0; k *= 10, e--) ;
1111           if (negexp)
1112             {
1113               d /= k;
1114             }
1115           else
1116             {
1117               d *= k;
1118             }
1119         }
1120     }
1122   if (neg)
1123     {
1124       d *= -1.0;
1125     }
1127   return d;
1131  * Convert (some) escaped characters into their ascii values
1132  */
1133 static char
1134 idl_escape_reader (char *str)
1136   if (str[0] != '\\')
1137     {
1138       return str[0];
1139     }
1141   switch (str[1])
1142   {
1143     case 'n':
1144       return '\n';
1145     case 't':
1146       return '\t';
1147     case 'v':
1148       return '\v';
1149     case 'b':
1150       return '\b';
1151     case 'r':
1152       return '\r';
1153     case 'f':
1154       return '\f';
1155     case 'a':
1156       return '\a';
1157     case '\\':
1158       return '\\';
1159     case '\?':
1160       return '?';
1161     case '\'':
1162       return '\'';
1163     case '"':
1164       return '"';
1165     case 'x':
1166       {
1167         int i;
1169         // hex value
1170         for (i = 2; str[i] != '\0' && isxdigit (str[i]); ++i)
1171           {
1172             continue;
1173           }
1175         char save = str[i];
1176         str[i] = '\0';
1177         char out = (char)idl_atoui(&str[2], 16);
1178         str[i] = save;
1179         return out;
1180       }
1181       ACE_NOTREACHED (break;)
1182     default:
1183       // check for octal value
1184       if (str[1] >= '0' && str[1] <= '7')
1185         {
1186           int i;
1188           for (i = 1; str[i] >= '0' && str[i] <= '7'; ++i)
1189             {
1190               continue;
1191             }
1193           char save = str[i];
1194           str[i] = '\0';
1195           char out = (char)idl_atoui(&str[1], 8);
1196           str[i] = save;
1197           return out;
1198         }
1199       else
1200         {
1201           return str[1] - 'a';
1202         }
1203       ACE_NOTREACHED  (break;)
1204   }
1207  * Convert escaped hex digits into a wchar
1208  */
1209 static ACE_CDR::WChar
1210 idl_wchar_escape_reader (char *str)
1212   if (str[0] != '\\' || str[1] != 'u')
1213     {
1214       return 0;
1215     }
1217   int i;
1218   // get the hex digits
1219   for (i = 2; str[i] != '\0' && isxdigit (str[i]); i++)
1220     {
1221       continue;
1222     }
1223   char save = str[i];
1224   str[i] = '\0';
1225   ACE_CDR::WChar out = (ACE_CDR::WChar) idl_atoui (&str[2], 16);
1226   str[i] = save;
1227   return out;
1231  * Checks wstring for validity
1232  */
1233 static char *
1234 idl_wstring_escape_reader (char *str)
1236   return str;
1239 static char *
1240 idl_get_pragma_string (char *pragma)
1242   // Get pointers to each end of the substring between the quotes.
1243   const char *firstquote = ACE_OS::strchr (pragma, '"');
1245   if (!firstquote)
1246     {
1247       idl_global->err ()->syntax_error (IDL_GlobalData::PS_PragmaPrefixSyntax);
1249       return nullptr;
1250     }
1252   const char *start = firstquote + 1;
1253   const char *end = ACE_OS::strchr (start, '"');
1255   if (!end)
1256     {
1257       idl_global->err ()->syntax_error (IDL_GlobalData::PS_PragmaPrefixSyntax);
1259       return nullptr;
1260     }
1262   size_t const len = end - start;
1263   char *retval {};
1265   ACE_NEW_RETURN (retval,
1266                   char[len + 1],
1267                   nullptr);
1269   ACE_OS::strncpy (retval,
1270                    start,
1271                    len);
1273   retval[len] = '\0';
1274   return retval;
1277 static bool
1278 idl_valid_version (char *s)
1280   // Nothing preceding decimal point.
1281   if (*s == '.')
1282     {
1283       return 0;
1284     }
1286   char *minor = ACE_OS::strchr (s, '.');
1287   int i;
1289   if (minor == 0)
1290     {
1291       // No decimal point.
1292       return 0;
1293     }
1295   if (*(minor + 1) == '\0')
1296     {
1297       // Nothing following decimal point.
1298       return 0;
1299     }
1301   char *tmp = minor + 1;
1303   for (i = 0; tmp[i] != '\0'; ++i)
1304     {
1305       if (!isdigit (tmp[i]))
1306         {
1307           return 0;
1308         }
1309     }
1311   ptrdiff_t const len = minor - s;
1313   for (i = 0; i < len; ++i)
1314     {
1315       if (!isdigit (s[i]))
1316         {
1317           return 0;
1318         }
1319     }
1321   // Major and minor version numbers must be unsigned shorts.
1322   if (ACE_OS::atoi (minor + 1) > ACE_UINT16_MAX
1323       || ACE_OS::atoi (s) > ACE_UINT16_MAX)
1324     {
1325       return 0;
1326     }
1328   return 1;
1331 static AST_Decl *
1332 idl_find_node (const char *s)
1334   UTL_ScopedName * node = FE_Utils::string_to_scoped_name (s);
1335   AST_Decl * d = 0;
1337   if (node != 0)
1338     {
1339       d = idl_global->scopes ().top_non_null ()->lookup_by_name (node);
1341       if (d == 0)
1342         {
1343           idl_global->err ()->lookup_error (node);
1344         }
1346       node->destroy ();
1347       delete node;
1348     }
1350   return d;