Merge pull request #2216 from jwillemsen/jwi-cxxversionchecks
[ACE_TAO.git] / TAO / TAO_IDL / fe / idl.ll
blob4306c74383201746a436c7a49aa383948cc54579
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 map             return IDL_MAP;
142 union           return IDL_UNION;
143 fixed           return IDL_FIXED;
144 switch          return IDL_SWITCH;
145 case            return IDL_CASE;
146 default         return IDL_DEFAULT;
147 float           return IDL_FLOAT;
148 double          return IDL_DOUBLE;
149 long            return IDL_LONG;
150 short           return IDL_SHORT;
151 unsigned        return IDL_UNSIGNED;
152 char            return IDL_CHAR;
153 wchar           return IDL_WCHAR;
154 boolean         return IDL_BOOLEAN;
155 octet           return IDL_OCTET;
156 void            return IDL_VOID;
157 native          return IDL_NATIVE;
158 local           return IDL_LOCAL;
159 abstract        return IDL_ABSTRACT;
161 int8 {
162   if (idl_global->idl_version_ >= IDL_VERSION_4)
163     return IDL_INT8;
164   else
165     {
166       REJECT;
167     }
169 uint8 {
170   if (idl_global->idl_version_ >= IDL_VERSION_4)
171     return IDL_UINT8;
172   else
173     {
174       REJECT;
175     }
177 int16 {
178   if (idl_global->idl_version_ >= IDL_VERSION_4)
179     return IDL_INT16;
180   else
181     {
182       REJECT;
183     }
185 uint16 {
186   if (idl_global->idl_version_ >= IDL_VERSION_4)
187     return IDL_UINT16;
188   else
189     {
190       REJECT;
191     }
193 int32 {
194   if (idl_global->idl_version_ >= IDL_VERSION_4)
195     return IDL_INT32;
196   else
197     {
198       REJECT;
199     }
201 uint32 {
202   if (idl_global->idl_version_ >= IDL_VERSION_4)
203     return IDL_UINT32;
204   else
205     {
206       REJECT;
207     }
209 int64 {
210   if (idl_global->idl_version_ >= IDL_VERSION_4)
211     return IDL_INT64;
212   else
213     {
214       REJECT;
215     }
217 uint64 {
218   if (idl_global->idl_version_ >= IDL_VERSION_4)
219     return IDL_UINT64;
220   else
221     {
222       REJECT;
223     }
225 map {
226   if (idl_global->idl_version_ >= IDL_VERSION_4)
227     return IDL_MAP;
228   else
229     {
230       REJECT;
231     }
234 custom          return IDL_CUSTOM;
235 factory         return IDL_FACTORY;
236 private         return IDL_PRIVATE;
237 public          return IDL_PUBLIC;
238 supports        return IDL_SUPPORTS;
239 truncatable     return IDL_TRUNCATABLE;
240 valuetype       return IDL_VALUETYPE;
242 component       return IDL_COMPONENT;
243 consumes        return IDL_CONSUMES;
244 emits           return IDL_EMITS;
245 eventtype       return IDL_EVENTTYPE;
246 finder          return IDL_FINDER;
247 getraises       return IDL_GETRAISES;
248 home            return IDL_HOME;
249 import          return IDL_IMPORT;
250 multiple        return IDL_MULTIPLE;
251 primarykey      return IDL_PRIMARYKEY;
252 provides        return IDL_PROVIDES;
253 publishes       return IDL_PUBLISHES;
254 setraises       return IDL_SETRAISES;
255 typeid          return IDL_TYPEID;
256 typeprefix      return IDL_TYPEPREFIX;
257 uses            return IDL_USES;
258 manages         return IDL_MANAGES;
260 typename        return IDL_TYPENAME;
261 port            return IDL_PORT;
262 mirrorport      return IDL_MIRRORPORT;
263 porttype        return IDL_PORTTYPE;
264 connector       return IDL_CONNECTOR;
265 alias           return IDL_ALIAS;
267 TRUE            return IDL_TRUETOK;
268 FALSE           return IDL_FALSETOK;
270 inout           return IDL_INOUT;
271 in              return IDL_IN;
272 out             return IDL_OUT;
273 oneway          return IDL_ONEWAY;
275 \<\<            return IDL_LEFT_SHIFT;
276 \>\>            return IDL_RIGHT_SHIFT;
277 \:\:            {
278                   tao_yylval.strval = ACE::strnew ("::");
279                   return IDL_SCOPE_DELIMITOR;
280                 }
282 @annotation[^A-Za-z0-9_] return IDL_ANNOTATION_DECL; // Allow annotation names that start with "annotation"
283 @ return IDL_ANNOTATION_SYMBOL;
285 [a-ij-rs-zA-IJ-RS-Z_][a-ij-rs-zA-IJ-RS-Z0-9_]* {
286   // Make sure that this identifier is not a C++ keyword. If it is,
287   // prepend it with a _cxx_. Lookup in the perfect hash table for C++
288   // keyword and grab the mapping.  BTW, the reason for the odd
289   // regular expression is to handle EBCDIC, as well as ASCII.
291   TAO_IDL_CPP_Keyword_Table cpp_key_tbl;
292   const TAO_IDL_CPP_Keyword_Entry *entry = 0;
293   if (!idl_global->preserve_cpp_keywords())
294     {
295       // This check will ensure that escaped C++ keywords will be
296       // caught and prepended with '_cxx' as non-escaped keywords
297       // are now prepended with '_cxx_'.
298       const char *tmp =
299         ace_yytext[0] == '_' ? ace_yytext + 1 : ace_yytext;
301       entry =
302         cpp_key_tbl.lookup (tmp,
303                             static_cast<unsigned int> (ACE_OS::strlen (tmp)));
304     }
306   if (entry)
307     {
308       tao_yylval.strval = ACE::strnew (entry->mapping_);
309     }
310   else
311     {
312       tao_yylval.strval = ACE::strnew (ace_yytext);
313     }
315   return IDENTIFIER;
318 "-"?(([0-9]+"."[0-9]*)|("."[0-9]+))([eE][+-]?[0-9]+)?[lLfF]?      {
319                   tao_yylval.dval = idl_atof (ace_yytext);
320                   return IDL_FLOATING_PT_LITERAL;
321                 }
322 "-"?[0-9]+[eE][+-]?[0-9]+[lLfF]?  {
323                   tao_yylval.dval = idl_atof (ace_yytext);
324                   return IDL_FLOATING_PT_LITERAL;
325                 }
327 "-"?(([0-9]+"."[0-9]*)|("."?[0-9]+))[dD] {
328                   tao_yylval.fixval = ACE_CDR::Fixed::from_string (ace_yytext);
329                   return IDL_FIXED_PT_LITERAL;
330                 }
332 "-"[1-9][0-9]*  {
333                   tao_yylval.ival = idl_atoi (ace_yytext, 10);
334                   return IDL_INTEGER_LITERAL;
335                 }
336 [1-9][0-9]*     {
337                   tao_yylval.uival = idl_atoui (ace_yytext, 10);
338                   return IDL_UINTEGER_LITERAL;
339                 }
340 "-"0[xX][a-fA-F0-9]+ {
341                   tao_yylval.ival = idl_atoi (ace_yytext, 16);
342                   return IDL_INTEGER_LITERAL;
343                 }
344 0[xX][a-fA-F0-9]+ {
345                   tao_yylval.uival = idl_atoui (ace_yytext, 16);
346                   return IDL_UINTEGER_LITERAL;
347                 }
348 "-"0[0-7]*      {
349                   tao_yylval.ival = idl_atoi (ace_yytext, 8);
350                   return IDL_INTEGER_LITERAL;
351                 }
352 0[0-7]*         {
353                   tao_yylval.uival = idl_atoui (ace_yytext, 8);
354                   return IDL_UINTEGER_LITERAL;
355                 }
357 (\"([^\\\"]*|\\[ntvbrfax\\\?\'\"]|\\[0-7]{1,3})*\"[ \t]*)+ {
358                   /* Skip the quotes */
359                   char * const tmp = ace_yytext;
360                   for (size_t i = ACE_OS::strlen (tmp); i-- != 0; )
361                     {
362                       if (isspace (tmp[i]))
363                         {
364                           tmp[i] = '\0';
365                         }
366                       else
367                         {
368                           break;
369                         }
370                     }
371                   tmp[ACE_OS::strlen (tmp) - 1] = '\0';
372                   ACE_NEW_RETURN (tao_yylval.sval,
373                                   UTL_String (tmp + 1, true),
374                                   IDL_STRING_LITERAL);
375                   return IDL_STRING_LITERAL;
376                 }
377 (L\"([^\\\"]*|\\[ntvbrfax\\\?\'\"]|\\[0-7]{1,3}|\\u([0-9a-fA-F]{1,4}))*\"[ \t]*)+ {
378                   /* Skip the bookends */
379                   char * const tmp = ACE_OS::strdup (ace_yytext);
380                   for (size_t i = ACE_OS::strlen (tmp); i-- != 0; )
381                     {
382                       if (isspace (tmp[i]))
383                         {
384                           tmp[i] = '\0';
385                         }
386                       else
387                         {
388                           break;
389                         }
390                     }
391                   tmp[ACE_OS::strlen (tmp) - 1] = '\0';
392                   tao_yylval.wsval = ACE_OS::strdup (idl_wstring_escape_reader (tmp + 2));
393                   ACE_OS::free (tmp);
394                   return IDL_WSTRING_LITERAL;
395                 }
396 "'"."'"         {
397                   tao_yylval.cval = ace_yytext[1];
398                   return IDL_CHARACTER_LITERAL;
399                 }
400 "'"\\([0-7]{1,3})"'" {
401                   // octal character constant
402                   tao_yylval.cval = idl_escape_reader (ace_yytext + 1);
403                   return IDL_CHARACTER_LITERAL;
404                 }
405 "'"\\[xX]([0-9a-fA-F]{1,2})"'" {
406                   // hexadecimal character constant
407                   tao_yylval.cval = idl_escape_reader (ace_yytext + 1);
408                   return IDL_CHARACTER_LITERAL;
409                 }
410 "'"\\."'"       {
411                   tao_yylval.cval = idl_escape_reader (ace_yytext + 1);
412                   return IDL_CHARACTER_LITERAL;
413                 }
414 L"'"."'"        {
415                   // wide character constant
416                   tao_yylval.wcval = ace_yytext[2];
417                   return IDL_WCHAR_LITERAL;
418                 }
419 L"'"\\u([0-9a-fA-F]{1,4})"'" {
420                   // hexadecimal wide character constant
421                   tao_yylval.wcval = idl_wchar_escape_reader (ace_yytext + 2);
422                   return IDL_WCHAR_LITERAL;
423                 }
424 ^[ \t]*#[ \t]*pragma[ \t].*{NL} |
425 ^\?\?=[ \t]*pragma[ \t].*{NL} {/* remember pragma */
426                   idl_global->set_lineno (idl_global->lineno () + 1);
427                   idl_store_pragma (ace_yytext);
428                   break;
429                 }
430 ^[ \t]*#file[ \t].*{NL} |
431 ^\?\?=[ \t]*file[ \t].*{NL} {/* ignore file */
432                   idl_global->set_lineno(idl_global->lineno () + 1);
433                   break;
434                 }
435 ^[ \t]*#[ \t]*[0-9]*" ""\""[^\"]*"\""" "[0-9]*([ \t]*[0-9]*)*{NL} |
436 ^\?\?=[ \t]*[0-9]*" ""\""[^\"]*"\""" "[0-9]*([ \t]*[0-9]*)?{NL} {
437                   idl_parse_line_and_file (ace_yytext);
438                   break;
439                 }
440 ^[ \t]*#[ \t]*[0-9]*" ""\""[^\"]*"\""{NL} |
441 ^\?\?=[ \t]*[0-9]*" ""\""[^\"]*"\""{NL} {
442                   idl_parse_line_and_file (ace_yytext);
443                   break;
444                 }
445 ^[ \t]*#line[ \t]*[0-9]+[ \t]*("\""[^\"]*"\""([ \t]*[0-9]*([ \t]*[0-9]*)?)?)?{NL} |
446 ^\?\?=line[ \t]*[0-9]*" ""\""[^\"]*"\""{NL} {
447                   idl_parse_line_and_file (ace_yytext);
448                   break;
449                 }
450 ^[ \t]*#[ \t]*[0-9]*{NL} |
451 ^\?\?=[ \t]*[0-9]*{NL} {
452                   idl_parse_line_and_file (ace_yytext);
453                   break;
454                 }
455 ^[ \t]*#[ \t]*ident[ \t].*{NL} |
456 ^\?\?=[ \t]*ident[ \t].*{NL} {
457                   /* ignore cpp ident */
458                   idl_global->set_lineno (idl_global->lineno () + 1);
459                   break;
460                 }
461 \/\/.*{NL}      {
462                   /* ignore comments */
463                   idl_global->set_lineno(idl_global->lineno () + 1);
464                   break;
465                 }
466 "/*"            {
467                   for (;;)
468                     {
469                       char const c = yyinput ();
470                       if (c == '*')
471                         {
472                           char const next = yyinput ();
473                           if (next == '/')
474                             break;
475                           else
476                             yyunput (c, 0);
477                         }
478                       else if (c == '\n')
479                         {
480                           idl_global->set_lineno (idl_global->lineno () + 1);
481                         }
482                     }
483                   break;
484                 }
485 [ \t]*          break;
486 {NL}            {
487                   idl_global->set_lineno (idl_global->lineno () + 1);
488                   break;
489                 }
490 .               return ace_yytext[0];
493         /* subroutines */
495 static bool
496 same_file (char *path1, char *path2)
498   char fullpath1 [MAXPATHLEN + 1] = {0};
499   char fullpath2 [MAXPATHLEN + 1] = {0};
501   char *fp1 = ACE_OS::realpath (path1, fullpath1);
502   char *fp2 = ACE_OS::realpath (path2, fullpath2);
504   return
505     (fp1 == 0 || fp2 == 0)
506       ? false
507       : FE_Utils::path_cmp (fullpath1,fullpath2) == 0;
510 // Parse a #line statement generated by the C preprocessor
511 static void
512 idl_parse_line_and_file (char *buf)
514   char *r = buf;
515   char *h = 0;
516   UTL_String *nm = 0;
518   // Skip initial '#'.
519   if (*r != '#')
520     {
521       return;
522     }
523   else
524     {
525       ++r;
526     }
528   // Check to see if we're running under the screwy Microsoft scheme
529   // of putting #line num instead of #num.
531   if (ACE_OS::strncmp (r, "line", 4) == 0)
532     {
533       r += 5;
534     }
536   // Find line number.
537   while (isspace (*r))
538     {
539       ++r;
540     }
542   h = r;
544   for (; isdigit (*r); ++r)
545     {
546       continue;
547     }
549   *r++ = 0;
550   idl_global->set_lineno ((long) idl_atoui (h, 10));
552   // Find file name, if present.
553   for (; *r != '"'; ++r)
554     {
555       if (*r == '\n' || *r == '\0')
556         {
557           return;
558         }
559     }
561   h = ++r;
563   for (; *r != '"'; ++r)
564     {
565       continue;
566     }
568   *r = 0;
569   UTL_String *tmp = 0;
571   if (*h == '\0')
572     {
573       ACE_ERROR ((LM_ERROR,
574                   ACE_TEXT ("IDL: No input files\n")));
576       throw Bailout ();
577     }
578   else
579     {
580       long i;
581       long j;
583       // Put Microsoft-style pathnames into a canonical form.
584       for (i = 0, j = 0; h[j] != '\0'; i++, j++)
585         {
586           if (h[j] == '\\' && h[j + 1] == '\\')
587             {
588               j++;
589             }
591             h[i] = h[j];
592         }
594       h[i] = '\0';
595       ACE_NEW (tmp,
596                UTL_String (h, true));
597       idl_global->update_prefix (tmp->get_string ());
598       idl_global->set_filename (tmp);
599     }
601   UTL_String *fname = idl_global->filename ();
602   bool in_main_file = false;
604   bool is_real_filename =
605     fname->compare (idl_global->real_filename ())
606     || same_file (fname->get_string(),
607                   idl_global->real_filename ()->get_string ());
609   bool is_main_filename = false;
611   if (!is_real_filename)
612     {
613       is_main_filename =
614         fname->compare (idl_global->main_filename ())
615         || same_file (fname->get_string (),
616                       idl_global->main_filename ()->get_string ());
617     }
619   if (is_real_filename || is_main_filename)
620     {
621       in_main_file = true;
622     }
624   idl_global->set_in_main_file (in_main_file);
626   // Strip off any command line -I prefix that may have been added
627   // by the preprocessor.
628   if (!(idl_global->in_main_file ()) && idl_global->import ())
629     {
630       ACE_NEW (nm,
631                UTL_String (
632                  FE_Utils::stripped_preproc_include (
633                    fname->get_string ()), true));
635       // This call also manages the #pragma prefix.
636       idl_global->store_include_file_name (nm);
637     }
640 // Store a #pragma line into the list of pragmas
641 static void
642 idl_store_pragma (char *buf)
644   char *sp = buf + 1;
645   int crunched = 0;
647   // Remove all the blanks between the '#' and the 'pragma'.
648   while (*sp != 'p')
649     {
650       ++sp;
651       ++crunched;
652     }
654   char *tp = buf + 1;
656   // This copies the crunched string back to the original, and
657   // also compensates for the behavior of the Sun preprocessor,
658   // which put spaces around the double colons of a non-quoted
659   // scoped name, a case which is possible in #pragma version.
660   // Also eats whitespace, which some preprocessors (for example
661   // Intel) don't automatically do.
662   while (*sp != '\n')
663     {
664       if (*sp == ' ' && (*(sp + 1) == ':' || *(sp + 1) == ' '))
665         {
666           ++crunched;
667         }
668       else if (*sp == ':' && *(sp + 1) == ' ')
669         {
670           *tp = *sp;
671           ++crunched;
672           ++sp;
673           ++tp;
674         }
675       else
676         {
677           *tp = *sp;
678           ++tp;
679         }
681       ++sp;
682     }
684   // The '\n' is still <crunched> spaces too far away, with
685   // garbage characters in between.
686   sp -= crunched;
687   *sp = '\0';
689   if (ACE_OS::strstr (buf + 8, "import") != 0)
690     {
691       idl_global->set_import (true);
692       return;
693     }
695   if (ACE_OS::strstr (buf + 8, "include") != 0)
696     {
697       idl_global->set_import (false);
698       return;
699     }
701   if (ACE_OS::strncmp (buf + 8, "prefix", 6) == 0)
702     {
703       char *new_prefix = idl_get_pragma_string (buf);
705       if (new_prefix != 0)
706         {
707           unsigned long depth = idl_global->scopes ().depth ();
709           // We replace the prefix only if there is a prefix already
710           // associated with this file, otherwise we add the prefix.
711           char *ext_id = idl_global->filename ()->get_string ();
712           ACE_Hash_Map_Entry<char *, char *> *entry = 0;
713           int const status =
714             idl_global->file_prefixes ().find (ext_id, entry);
716           if (status == 0)
717             {
718               if (ACE_OS::strcmp (entry->int_id_, "") != 0)
719                 {
720                   char *trash = 0;
721                   idl_global->pragma_prefixes ().pop (trash);
722                   delete [] trash;
723                 }
724               else if (depth == 1)
725                 {
726                   // Remove the default "" and bind the new prefix.
727                   ACE::strdelete (entry->ext_id_);
728                   ACE::strdelete (entry->int_id_);
729                   (void) idl_global->file_prefixes ().unbind (entry);
730                   (void) idl_global->file_prefixes ().bind (ACE::strnew (ext_id),
731                                                             ACE::strnew (new_prefix));
732                 }
733             }
735           UTL_Scope *top_scope = idl_global->scopes ().top ();
737           if (depth > 1)
738             {
739               top_scope->has_prefix (true);
740               ScopeAsDecl (top_scope)->prefix_scope (top_scope);
741             }
743           idl_global->pragma_prefixes ().push (new_prefix);
745           if (depth == 1)
746             {
747               idl_global->root ()->prefix (new_prefix);
748             }
750           if (idl_global->in_main_file ())
751             {
752               idl_global->root ()->set_imported (false);
753               top_scope->has_prefix (true);
754             }
756           if (status != 0)
757             {
758               (void) idl_global->file_prefixes ().bind (ACE::strnew (ext_id),
759                                                         ACE::strnew (new_prefix));
760             }
761         }
762     }
763   else if (ACE_OS::strncmp (buf + 8, "version", 7) == 0)
764     {
765       char *tmp = buf + 16;
767       while (*tmp == ' ' || *tmp == '\t')
768         {
769           ++tmp;
770         }
772       char *number = ACE_OS::strchr (tmp, ' ');
774       if (number == 0)
775         {
776           number = ACE_OS::strchr (tmp, '\t');
777         }
779       // Used later to trim the type string.
780       ptrdiff_t cutoff = number - tmp;
782       // Most likely this means there is only a version number
783       // without an identifier to apply it to.
784       if (number == 0)
785         {
786           const char *msg = "no identifier or scoped name";
787           idl_global->err ()->version_syntax_error (msg);
788           return;
789         }
791       while (*number == ' ' || *number == '\t')
792         {
793           ++number;
794         }
796       size_t len = ACE_OS::strlen (number);
798       // For some reason, the SunCC preprocessor adds a trailing space, which
799       // messes with idl_valid_version() below, so we check and remove.
800       while (number[len - 1] == ' ')
801         {
802           number[len - 1] = '\0';
803           len = ACE_OS::strlen (number);
804         }
806       // Trim the type string after trimming the number string.
807       tmp[cutoff] = '\0';
809       // This call adds a proper null terminator to tmp, so no need to
810       // do it here.
811       AST_Decl *d = idl_find_node (tmp);
813       if (d == 0)
814         {
815           return;
816         }
818       if (!idl_valid_version (number))
819         {
820           idl_global->err ()->version_number_error (number);
821           return;
822         }
824       d->version (ACE::strnew (number));
825     }
826   else if (ACE_OS::strncmp (buf + 8, "ident", 5) == 0)
827     {
828       idl_global->ident_string (buf + 8);
829     }
830   else if (ACE_OS::strncmp (buf + 8, "ID", 2) == 0)
831     {
832       char *tmp = buf + 11;
834       while (*tmp == ' ')
835         {
836           ++tmp;
837         }
839       ACE_CString work (tmp);
840       work = work.substr (0, work.find (' '));
842       AST_Decl *d = idl_find_node (work.c_str ());
844       if (d == 0)
845         {
846           return;
847         }
849       char *new_id = idl_get_pragma_string (buf);
851       if (new_id != 0)
852         {
853           if (d->typeid_set ())
854             {
855               idl_global->err ()->id_reset_error (d->repoID (),
856                                                   new_id);
857               return;
858             }
860           d->repoID (new_id);
861           d->typeid_set (true);
862         }
863     }
864   else if (ACE_OS::strncmp (buf + 8, "DCPS_DATA_TYPE", 14) == 0)
865     {
866       char *sample_type = idl_get_pragma_string (buf);
867       idl_global->add_dcps_data_type (sample_type);
869       // Delete sample_type since add_dcps_data_type() doesn't take its ownership.
870       delete [] sample_type;
871     }
872   else if (ACE_OS::strncmp (buf + 8, "DCPS_DATA_KEY", 13) == 0)
873     {
874       char *tmp = idl_get_pragma_string (buf);
876       // Split up data type and key strings
877       char *sample_type = tmp;
879       while (*tmp && !isspace (*tmp))
880         {
881           ++tmp;
882         }
884       while (isspace (*tmp))
885         {
886           *tmp = '\0';
887           tmp++;
888         }
890       char *key = tmp;
892       if (!idl_global->add_dcps_data_key (sample_type, key))
893         {
894           ACE_ERROR((LM_ERROR, "DCPS_DATA_TYPE \"%C\" not found for key \"%C\"\n",
895             sample_type, key));
896         }
898       // Delete sample_type since add_dcps_data_key() doesn't take its ownership.
899       delete [] sample_type;
900     }
901   else if (ACE_OS::strncmp (buf + 8, "DCPS_DATA_SEQUENCE_TYPE", 23) == 0)
902     {
903       char *seq_type = idl_get_pragma_string (buf);
904       idl_global->set_dcps_sequence_type (seq_type);
906       delete [] seq_type;
907     }
908   else if (ACE_OS::strncmp (buf + 8, "DCPS_SUPPORT_ZERO_COPY_READ", 27) == 0)
909     {
910       idl_global->dcps_support_zero_copy_read (true);
911     }
912   else if (ACE_OS::strncmp (buf + 8, "DCPS_GEN_ZERO_COPY_READ", 23) == 0)
913     {
914       idl_global->dcps_gen_zero_copy_read (true);
915     }
916   else if (ACE_OS::strncmp (buf + 8, "ciao lem", 8) == 0)
917     {
918       char *tmp = idl_get_pragma_string (buf);
919       idl_global->add_ciao_lem_file_names (tmp);
921       // Delete tmp since add_ciao_lem_file_names() doesn't take its ownership.
922       delete [] tmp;
923     }
924   else if (ACE_OS::strncmp (buf + 8, "ndds typesupport", 16) == 0)
925     {
926       char *tmp = idl_get_pragma_string (buf);
927       idl_global->add_ciao_rti_ts_file_names (tmp);
929       // Delete tmp since add_ciao_rti_ts_file_names() doesn't take its ownership.
930       delete [] tmp;
931     }
932   else if (ACE_OS::strncmp (buf + 8, "coredx typesupport", 18) == 0)
933     {
934       char *tmp = idl_get_pragma_string (buf);
935       idl_global->add_ciao_coredx_ts_file_names (tmp);
937       // Delete tmp since add_ciao_coredx_ts_file_names() doesn't take its ownership.
938       delete [] tmp;
939     }
940   else if (ACE_OS::strncmp (buf + 8, "opendds typesupport", 19) == 0)
941     {
942       char *tmp = idl_get_pragma_string (buf);
943       idl_global->add_ciao_oci_ts_file_names (tmp);
945       // Delete tmp since add_ciao_oci_ts_file_names() doesn't take its ownership.
946       delete [] tmp;
947     }
948   else if (ACE_OS::strncmp (buf + 8, "splice typesupport", 18) == 0)
949     {
950       char *tmp = idl_get_pragma_string (buf);
951       idl_global->add_ciao_spl_ts_file_names (tmp);
953       // Delete tmp since add_ciao_spl_ts_file_names() doesn't take its ownership.
954       delete [] tmp;
955     }
956   else if ((ACE_OS::strncmp (buf + 8, "ciao ami4ccm interface", 22) == 0) ||
957            (ACE_OS::strncmp (buf + 8, "ami4ccm interface", 17) == 0))
958     {
959       if (idl_global->in_main_file ())
960         {
961           char *tmp = idl_get_pragma_string (buf);
962           idl_global->add_ciao_ami_iface_names (tmp);
964           // Delete tmp since add_ciao_ami_iface_names() doesn't take its ownership.
965           delete [] tmp;
966         }
967     }
968   else if ((ACE_OS::strncmp (buf + 8, "ciao ami4ccm receptacle", 23) == 0) ||
969            (ACE_OS::strncmp (buf + 8, "ami4ccm receptacle", 18) == 0))
970     {
971       char *tmp = idl_get_pragma_string (buf);
973       if (idl_global->in_main_file ())
974         {
975           idl_global->add_ciao_ami_recep_names (tmp);
976         }
977       else
978         {
979           /// This is intended for the executor IDL file,
980           /// when a pragma is seen in the main file, but
981           /// it will do no harm in other cases.
982           idl_global->add_included_ami_recep_names (tmp);
983         }
985       // Delete tmp since add_ciao_spl_ts_file_names() doesn't take its ownership.
986       delete [] tmp;
987     }
988   else if ((ACE_OS::strncmp (buf + 8, "ciao ami4ccm idl", 16) == 0) ||
989            (ACE_OS::strncmp (buf + 8, "ami4ccm idl", 11) == 0))
990     {
991       char *tmp = idl_get_pragma_string (buf);
993       /// These pragmas are found in the file where the interface
994       /// that has a AMI4CCM_* counterpart in the *A.idl file
995       /// is declared. We add the filename to the list in all
996       /// IDL files *except* the one where it is found, to
997       /// eliminate a circular include of xxxC.h and xxxAC.h.
998       if (!idl_global->in_main_file ())
999         {
1000           idl_global->add_ciao_ami_idl_fnames (tmp);
1001         }
1003       // Delete tmp since add_ciao_ami_idl_fnames() doesn't take its ownership.
1004       delete [] tmp;
1005     }
1006   else if (ACE_OS::strncmp (buf + 8, "dds4ccm impl", 12) == 0)
1007     {
1008       char *tmp = idl_get_pragma_string (buf);
1010       idl_global->add_dds4ccm_impl_fnames (tmp);
1012       // Delete tmp since add_dds4ccm_impl_fnames() doesn't take its ownership.
1013       delete [] tmp;
1014     }
1018  * idl_atoi - Convert a string of digits into a negative integer according to base b
1019  */
1020 static ACE_CDR::LongLong
1021 idl_atoi (char *s, long b)
1023   ACE_CDR::LongLong r = 0;
1025   // Skip over the dash and possibly spaces after the dash
1026   while (*s == '-' || *s == ' ' || *s == '\t')
1027     {
1028       ++s;
1029     }
1031   if (b == 8 && *s == '0')
1032     {
1033       ++s;
1034     }
1035   else if (b == 16 && *s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))
1036     {
1037       s += 2;
1038     }
1040   for (; *s; ++s)
1041     {
1042       if (*s <= '9' && *s >= '0')
1043         {
1044           r = (r * b) + (*s - '0');
1045         }
1046       else if (b > 10 && *s <= 'f' && *s >= 'a')
1047         {
1048           r = (r * b) + (*s - 'a' + 10);
1049         }
1050       else if (b > 10 && *s <= 'F' && *s >= 'A')
1051         {
1052           r = (r * b) + (*s - 'A' + 10);
1053         }
1054       else
1055         {
1056           break;
1057         }
1058     }
1060   return -r;
1064  * idl_atoui - Convert a string of digits into an unsigned integer according to base b
1065  */
1066 static ACE_CDR::ULongLong
1067 idl_atoui (char *s, long b)
1069   ACE_CDR::ULongLong r = 0;
1071   if (b == 8 && *s == '0')
1072     {
1073       ++s;
1074     }
1075   else if (b == 16 && *s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))
1076     {
1077       s += 2;
1078     }
1080   for (; *s; ++s)
1081     {
1082       if (*s <= '9' && *s >= '0')
1083         {
1084           r = (r * b) + (*s - '0');
1085         }
1086       else if (b > 10 && *s <= 'f' && *s >= 'a')
1087         {
1088           r = (r * b) + (*s - 'a' + 10);
1089         }
1090       else if (b > 10 && *s <= 'F' && *s >= 'A')
1091         {
1092           r = (r * b) + (*s - 'A' + 10);
1093         }
1094       else
1095         {
1096           break;
1097         }
1098     }
1100   return r;
1104  * Convert a string to a float; atof doesn't seem to work, always.
1105  */
1106 static ACE_CDR::Double
1107 idl_atof (char *s)
1109   double d = 0.0;
1110   double e, k;
1111   long neg = 0, negexp = 0;
1113   if (*s == '-')
1114     {
1115       neg = 1;
1117       // Skip over the dash and possibly spaces after the dash
1118       while (*s == '-' || *s == ' ' || *s == '\t')
1119         {
1120           ++s;
1121         }
1122     }
1124   while (*s >= '0' && *s <= '9')
1125     {
1126       d = (d * 10) + *s - '0';
1127       ++s;
1128     }
1130   if (*s == '.')
1131     {
1132       ++s;
1133       e = 10;
1135       while (*s >= '0' && *s <= '9')
1136         {
1137           d += (*s - '0') / (e * 1.0);
1138           e *= 10;
1139           ++s;
1140         }
1141     }
1143   if (*s == 'e' || *s == 'E')
1144     {
1145       ++s;
1147       if (*s == '-')
1148         {
1149             negexp = 1;
1150             s++;
1151         }
1152       else if (*s == '+')
1153         {
1154           ++s;
1155         }
1157       e = 0;
1159       while (*s >= '0' && *s <= '9')
1160         {
1161           e = (e * 10) + *s - '0';
1162           ++s;
1163         }
1165       if (e > 0)
1166         {
1167           for (k = 1; e > 0; k *= 10, e--) ;
1169           if (negexp)
1170             {
1171               d /= k;
1172             }
1173           else
1174             {
1175               d *= k;
1176             }
1177         }
1178     }
1180   if (neg)
1181     {
1182       d *= -1.0;
1183     }
1185   return d;
1189  * Convert (some) escaped characters into their ascii values
1190  */
1191 static char
1192 idl_escape_reader (char *str)
1194   if (str[0] != '\\')
1195     {
1196       return str[0];
1197     }
1199   switch (str[1])
1200   {
1201     case 'n':
1202       return '\n';
1203     case 't':
1204       return '\t';
1205     case 'v':
1206       return '\v';
1207     case 'b':
1208       return '\b';
1209     case 'r':
1210       return '\r';
1211     case 'f':
1212       return '\f';
1213     case 'a':
1214       return '\a';
1215     case '\\':
1216       return '\\';
1217     case '\?':
1218       return '?';
1219     case '\'':
1220       return '\'';
1221     case '"':
1222       return '"';
1223     case 'x':
1224       {
1225         int i;
1227         // hex value
1228         for (i = 2; str[i] != '\0' && isxdigit (str[i]); ++i)
1229           {
1230             continue;
1231           }
1233         char save = str[i];
1234         str[i] = '\0';
1235         char out = (char)idl_atoui(&str[2], 16);
1236         str[i] = save;
1237         return out;
1238       }
1239       ACE_NOTREACHED (break;)
1240     default:
1241       // check for octal value
1242       if (str[1] >= '0' && str[1] <= '7')
1243         {
1244           int i;
1246           for (i = 1; str[i] >= '0' && str[i] <= '7'; ++i)
1247             {
1248               continue;
1249             }
1251           char save = str[i];
1252           str[i] = '\0';
1253           char out = (char)idl_atoui(&str[1], 8);
1254           str[i] = save;
1255           return out;
1256         }
1257       else
1258         {
1259           return str[1] - 'a';
1260         }
1261       ACE_NOTREACHED  (break;)
1262   }
1265  * Convert escaped hex digits into a wchar
1266  */
1267 static ACE_CDR::WChar
1268 idl_wchar_escape_reader (char *str)
1270   if (str[0] != '\\' || str[1] != 'u')
1271     {
1272       return 0;
1273     }
1275   int i;
1276   // get the hex digits
1277   for (i = 2; str[i] != '\0' && isxdigit (str[i]); i++)
1278     {
1279       continue;
1280     }
1281   char save = str[i];
1282   str[i] = '\0';
1283   ACE_CDR::WChar out = (ACE_CDR::WChar) idl_atoui (&str[2], 16);
1284   str[i] = save;
1285   return out;
1289  * Checks wstring for validity
1290  */
1291 static char *
1292 idl_wstring_escape_reader (char *str)
1294   return str;
1297 static char *
1298 idl_get_pragma_string (char *pragma)
1300   // Get pointers to each end of the substring between the quotes.
1301   const char *firstquote = ACE_OS::strchr (pragma, '"');
1303   if (!firstquote)
1304     {
1305       idl_global->err ()->syntax_error (IDL_GlobalData::PS_PragmaPrefixSyntax);
1307       return nullptr;
1308     }
1310   const char *start = firstquote + 1;
1311   const char *end = ACE_OS::strchr (start, '"');
1313   if (!end)
1314     {
1315       idl_global->err ()->syntax_error (IDL_GlobalData::PS_PragmaPrefixSyntax);
1317       return nullptr;
1318     }
1320   size_t const len = end - start;
1321   char *retval {};
1323   ACE_NEW_RETURN (retval,
1324                   char[len + 1],
1325                   nullptr);
1327   ACE_OS::strncpy (retval,
1328                    start,
1329                    len);
1331   retval[len] = '\0';
1332   return retval;
1335 static bool
1336 idl_valid_version (char *s)
1338   // Nothing preceding decimal point.
1339   if (*s == '.')
1340     {
1341       return 0;
1342     }
1344   char *minor = ACE_OS::strchr (s, '.');
1345   int i;
1347   if (minor == 0)
1348     {
1349       // No decimal point.
1350       return 0;
1351     }
1353   if (*(minor + 1) == '\0')
1354     {
1355       // Nothing following decimal point.
1356       return 0;
1357     }
1359   char *tmp = minor + 1;
1361   for (i = 0; tmp[i] != '\0'; ++i)
1362     {
1363       if (!isdigit (tmp[i]))
1364         {
1365           return 0;
1366         }
1367     }
1369   ptrdiff_t const len = minor - s;
1371   for (i = 0; i < len; ++i)
1372     {
1373       if (!isdigit (s[i]))
1374         {
1375           return 0;
1376         }
1377     }
1379   // Major and minor version numbers must be unsigned shorts.
1380   if (ACE_OS::atoi (minor + 1) > ACE_UINT16_MAX
1381       || ACE_OS::atoi (s) > ACE_UINT16_MAX)
1382     {
1383       return 0;
1384     }
1386   return 1;
1389 static AST_Decl *
1390 idl_find_node (const char *s)
1392   UTL_ScopedName * node = FE_Utils::string_to_scoped_name (s);
1393   AST_Decl * d = 0;
1395   if (node != 0)
1396     {
1397       d = idl_global->scopes ().top_non_null ()->lookup_by_name (node);
1399       if (d == 0)
1400         {
1401           idl_global->err ()->lookup_error (node);
1402         }
1404       node->destroy ();
1405       delete node;
1406     }
1408   return d;