5 Copyright 1992, 1993, 1994 Sun Microsystems, Inc. Printed in the United
6 States of America. All Rights Reserved.
8 This product is protected by copyright and distributed under the following
9 license restricting its use.
11 The Interface Definition Language Compiler Front End (CFE) is made
12 available for your use provided that you include this license and copyright
13 notice on all media and documentation and the software program in which
14 this product is incorporated in whole or part. You may copy and extend
15 functionality (but may not remove functionality) of the Interface
16 Definition Language CFE without charge, but you are not authorized to
17 license or distribute it to anyone else except as part of a product or
18 program developed by you or with the express written consent of Sun
19 Microsystems, Inc. ("Sun").
21 The names of Sun Microsystems, Inc. and any of its subsidiaries or
22 affiliates may not be used in advertising or publicity pertaining to
23 distribution of Interface Definition Language CFE as permitted herein.
25 This license is effective until terminated by Sun for failure to comply
26 with this license. Upon termination, you shall destroy or return all code
27 and documentation for the Interface Definition Language CFE.
29 INTERFACE DEFINITION LANGUAGE CFE IS PROVIDED AS IS WITH NO WARRANTIES OF
30 ANY KIND INCLUDING THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS
31 FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR ARISING FROM A COURSE OF
32 DEALING, USAGE OR TRADE PRACTICE.
34 INTERFACE DEFINITION LANGUAGE CFE IS PROVIDED WITH NO SUPPORT AND WITHOUT
35 ANY OBLIGATION ON THE PART OF Sun OR ANY OF ITS SUBSIDIARIES OR AFFILIATES
36 TO ASSIST IN ITS USE, CORRECTION, MODIFICATION OR ENHANCEMENT.
38 SUN OR ANY OF ITS SUBSIDIARIES OR AFFILIATES SHALL HAVE NO LIABILITY WITH
39 RESPECT TO THE INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY
40 INTERFACE DEFINITION LANGUAGE CFE OR ANY PART THEREOF.
42 IN NO EVENT WILL SUN OR ANY OF ITS SUBSIDIARIES OR AFFILIATES BE LIABLE FOR
43 ANY LOST REVENUE OR PROFITS OR OTHER SPECIAL, INDIRECT AND CONSEQUENTIAL
44 DAMAGES, EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
46 Use, duplication, or disclosure by the government is subject to
47 restrictions as set forth in subparagraph (c)(1)(ii) of the Rights in
48 Technical Data and Computer Software clause at DFARS 252.227-7013 and FAR
51 Sun, Sun Microsystems and the Sun logo are trademarks or registered
52 trademarks of Sun Microsystems, Inc.
56 Mountain View, California 94043
60 SunOS, SunSoft, Sun, Solaris, Sun Microsystems or the Sun logo are
61 trademarks or registered trademarks of Sun Microsystems, Inc.
65 // Pass an IDL file through the C preprocessor
68 #include "idl_defines.h"
69 #include "global_extern.h"
70 #include "fe_extern.h"
71 #include "drv_extern.h"
72 #include "utl_string.h"
75 #include "ace/Version.h"
76 #include "ace/Process.h"
77 #include "ace/SString.h"
78 #include "ace/Env_Value_T.h"
80 #include "ace/Dirent.h"
81 #include "ace/OS_NS_sys_stat.h"
82 #include "ace/Truncate.h"
84 // FUZZ: disable check_for_streams_include
85 #include "ace/streams.h"
87 #include "ace/OS_NS_stdio.h"
88 #include "ace/OS_NS_unistd.h"
89 #include "ace/OS_NS_fcntl.h"
90 #include "ace/OS_NS_sys_stat.h"
92 // Storage for preprocessor args.
93 unsigned long const DRV_MAX_ARGCOUNT
= 1024;
94 unsigned long DRV_argcount
= 0;
95 ACE_TCHAR
const * DRV_arglist
[DRV_MAX_ARGCOUNT
] = { nullptr };
97 static char const * output_arg_format
= nullptr;
98 static long output_arg_index
= 0;
100 ACE_TCHAR
const TCHAR_DIR_DOT
[] = ACE_TEXT(".");
102 #if defined (ACE_HAS_TCHAR_DIRENT)
103 // ACE_TCHAR const DIR_DOT[] = ACE_TEXT(".");
104 ACE_TCHAR
const DIR_DOT_DOT
[] = ACE_TEXT("..");
106 // char const DIR_DOT[] = ".";
107 char const DIR_DOT_DOT
[] = "..";
108 #endif /* ACE_HAS_TCHAR_DIRENT */
111 static char tmp_file
[MAXPATHLEN
+ 1] = { 0 };
112 static char tmp_ifile
[MAXPATHLEN
+ 1] = { 0 };
114 // Lines can be 1024 chars long intially -
115 // it will expand as required.
116 #define LINEBUF_SIZE 1024
117 char* drv_line
= nullptr;
118 static size_t drv_line_size
= LINEBUF_SIZE
+ 1;
120 // Push the new CPP location if we got a -Yp argument.
122 DRV_cpp_new_location (char const * new_loc
)
124 ACE::strdelete (const_cast<ACE_TCHAR
*> (DRV_arglist
[0]));
126 ACE::strnew (ACE_TEXT_CHAR_TO_TCHAR (new_loc
));
129 // Push an argument into the DRV_arglist.
131 DRV_cpp_putarg (const char *str
)
133 if (DRV_argcount
>= DRV_MAX_ARGCOUNT
)
135 ACE_ERROR ((LM_ERROR
,
136 "%C: More than %d arguments to preprocessor\n",
137 idl_global
->prog_name (),
143 char *replace
= nullptr;
146 bool allocate_error
= false;
149 const char *const first_quote
= ACE_OS::strchr (str
, '"');
152 // Escape Doublequotes on Windows
154 size_t quote_count
= 0;
155 for (const char *quote
= first_quote
; quote
; quote
= ACE_OS::strchr (quote
, '"'))
161 ACE_NEW_NORETURN (replace
, char[ACE_OS::strlen (str
) + quote_count
+ 1]);
162 allocate_error
= !replace
;
166 for (const char *from
= str
; *from
; ++from
)
180 if (ACE_OS::strchr (str
, ' '))
182 ACE_NEW_NORETURN (replace
, char[ACE_OS::strlen (str
) + 3]);
183 allocate_error
= !replace
;
187 ACE_OS::strcpy (replace
+ 1, str
);
188 ACE_OS::strcat (replace
, "\"");
194 idl_global
->err()->misc_error ("DRV_cpp_putarg failed to allocate memory for argument!");
199 DRV_arglist
[DRV_argcount
++] = ACE::strnew (ACE_TEXT_CHAR_TO_TCHAR (replace
? replace
: str
));
208 // Expand the output argument with the given filename.
210 DRV_cpp_expand_output_arg (const char *filename
)
212 if (output_arg_format
!= nullptr)
214 ACE::strdelete (const_cast<ACE_TCHAR
*> (
215 DRV_arglist
[output_arg_index
]));
216 DRV_arglist
[output_arg_index
] = nullptr;
218 ACE_NEW (DRV_arglist
[output_arg_index
],
219 ACE_TCHAR
[ACE_OS::strlen (output_arg_format
)
220 + ACE_OS::strlen (filename
)
223 ACE_OS::sprintf (const_cast<ACE_TCHAR
*> (
224 DRV_arglist
[output_arg_index
]),
225 ACE_TEXT_CHAR_TO_TCHAR (output_arg_format
),
226 ACE_TEXT_CHAR_TO_TCHAR (filename
));
230 // calculate the total size of all commandline arguments
232 DRV_cpp_calc_total_argsize()
234 unsigned long size
= 0;
235 unsigned long ix
= 0;
236 while (DRV_arglist
[ix
] != nullptr)
238 size
+= ACE_Utils::truncate_cast
<unsigned long> (ACE_OS::strlen (DRV_arglist
[ix
]) + 1);
244 // Get a line from stdin.
246 DRV_get_line (FILE *file
)
248 char *line
= ACE_OS::fgets (drv_line
,
249 ACE_Utils::truncate_cast
<int> (drv_line_size
),
251 if (!line
|| (!*line
&& feof (file
)))
253 // End of file, nothing else read in.
259 // Check for line continuation escape...
260 size_t len
= ACE_OS::strlen (drv_line
);
262 '\n' == drv_line
[len
-1] &&
263 '\\' == drv_line
[len
-2] )
265 // This is a "false" end-of-line, remove token
267 drv_line
[len
]= '\0';
270 // Check for end-of-line
271 if (len
&& '\n' == drv_line
[len
-1])
273 // Replace the end-of-line with a null
274 drv_line
[len
-1] = '\0';
278 // Need to continue to read more of this line in,
279 // is there enough space left in the buffer?
280 if (drv_line_size
- len
< 10)
282 // Create a bigger buffer
283 size_t temp_size
= drv_line_size
* 2;
284 char *temp
= nullptr;
285 ACE_NEW_RETURN (temp
, char [temp_size
], false);
286 ACE_OS::strcpy (temp
, drv_line
);
289 drv_line_size
= temp_size
;
292 line
= ACE_OS::fgets (drv_line
+ len
,
293 ACE_Utils::truncate_cast
<int> (drv_line_size
- len
),
295 } while (line
&& *line
);
300 // Initialize the cpp argument list.
304 // Create the line buffer.
305 // (JP) Deleting this at the end or DRV_pre_proc() causes
306 // Purify to output a Freeing Mismatched Memory warning.
307 // When it is not deleted (currently the case) there is no
308 // memory leak reported by Purify. I don't know why.
310 char [drv_line_size
]);
312 char const * const cpp_loc
= FE_get_cpp_loc_from_env ();
313 DRV_cpp_putarg (cpp_loc
);
315 // Add an option to the IDL compiler to make the TAO version
316 // available to the user. A XX.YY.ZZ release gets
317 // version 0xXXYYZZ, for example, 5.1.14 gets 0x050114.
318 char version_option
[128];
319 ACE_OS::sprintf (version_option
,
320 "-D__TAO_IDL=0x%2.2d%2.2d%2.2d",
325 DRV_cpp_putarg (version_option
);
326 DRV_cpp_putarg ("-I.");
328 const char *platform_cpp_args
=
329 FE_get_cpp_args_from_env ();
331 if (platform_cpp_args
== nullptr)
333 // If no cpp flag was defined by the user, we define some
334 // platform specific flags here.
336 #if defined (TAO_IDL_PREPROCESSOR_ARGS)
337 platform_cpp_args
= TAO_IDL_PREPROCESSOR_ARGS
;
338 #elif defined (ACE_CC_PREPROCESSOR_ARGS)
339 platform_cpp_args
= ACE_CC_PREPROCESSOR_ARGS
;
341 platform_cpp_args
= "-E";
342 #endif /* TAO_IDL_PREPROCESSOR_ARGS */
344 // So we can find OMG IDL files, such as `orb.idl'.
345 ACE_CString include_path1
, include_path2
;
347 char* TAO_ROOT
= ACE_OS::getenv ("TAO_ROOT");
349 if (TAO_ROOT
!= nullptr)
351 DRV_add_include_path (include_path1
,
356 DRV_add_include_path (include_path2
,
363 char* ACE_ROOT
= ACE_OS::getenv ("ACE_ROOT");
365 if (ACE_ROOT
!= nullptr)
367 DRV_add_include_path (include_path1
,
372 DRV_add_include_path (include_path2
,
379 #if defined (TAO_IDL_INCLUDE_DIR)
380 // TAO_IDL_INCLUDE_DIR may be in quotes,
381 // e.g. "/usr/local/include/tao"
382 // We deal with a case like this below ...
383 DRV_add_include_path (include_path1
,
387 DRV_add_include_path (include_path2
,
392 DRV_add_include_path (include_path1
,
396 #endif /* TAO_IDL_INCLUDE_DIR */
400 idl_global
->tao_root (include_path1
.c_str ());
403 // Add any flags in platform_cpp_args to cpp's DRV_arglist.
404 ACE_ARGV
platform_arglist (
405 ACE_TEXT_CHAR_TO_TCHAR (platform_cpp_args
));
407 for (int i
= 0; i
< platform_arglist
.argc (); ++i
)
409 // Check for an argument that specifies
410 // the preprocessor's output file.
411 if (ACE_OS::strstr (platform_arglist
[i
], ACE_TEXT ("%s")) != nullptr
412 && output_arg_format
== nullptr)
415 ACE::strnew (ACE_TEXT_ALWAYS_CHAR (platform_arglist
[i
]));
416 output_arg_index
= DRV_argcount
;
417 DRV_cpp_putarg (nullptr);
421 DRV_cpp_putarg (ACE_TEXT_ALWAYS_CHAR (platform_arglist
[i
]));
427 DRV_sweep_dirs (const char *rel_path
,
428 const char *base_path
)
430 // Zero rel_path means we're not using this option, and
431 // so we become a no-op.
432 if (rel_path
== nullptr)
437 if (ACE_OS::chdir (rel_path
) == -1)
439 ACE_ERROR_RETURN ((LM_ERROR
,
440 "DRV_sweep_dirs: chdir %C failed\n",
445 ACE_Dirent
dir (TCHAR_DIR_DOT
);
446 ACE_CString
bname (base_path
);
447 bname
+= (bname
.length () > 0 ? "/" : "");
449 bool include_added
= false;
450 char abspath
[MAXPATHLEN
] = "";
451 char *full_path
= nullptr;
453 for (ACE_DIRENT
*dir_entry
; (dir_entry
= dir
.read ()) != nullptr;)
455 // Skip the ".." and "." files in each directory.
456 if (ACE::isdotdir (dir_entry
->d_name
) == true)
461 #if defined (ACE_HAS_TCHAR_DIRENT)
462 ACE_CString
lname (ACE_TEXT_ALWAYS_CHAR (dir_entry
->d_name
));
464 ACE_CString
lname (dir_entry
->d_name
);
468 if (ACE_OS::lstat (lname
.c_str (), &stat_buf
) == -1)
470 ACE_ERROR_RETURN ((LM_ERROR
,
471 "DRV_sweep_dirs: ACE_OS::lstat"
479 switch (stat_buf
.st_mode
& S_IFMT
)
481 case S_IFREG
: // Either a regular file or an executable.
482 len
= lname
.length ();
484 if (len
> 4 && lname
.substr (len
- 4) == ".idl")
488 ACE_CString
incl_arg ("-I");
490 DRV_cpp_putarg (incl_arg
.c_str ());
491 idl_global
->add_rel_include_path (bname
.c_str ());
492 full_path
= ACE_OS::realpath ("", abspath
);
494 if (full_path
!= nullptr)
496 idl_global
->add_include_path (full_path
,
500 include_added
= true;
503 ACE_CString
fname (bname
);
506 DRV_push_file (fname
.c_str ());
510 case S_IFDIR
: // Subdirectory.
511 DRV_sweep_dirs (lname
.c_str (), bname
.c_str ());
513 case S_IFLNK
: // Either a file link or directory link.
514 default: // Some other type of file (PIPE/FIFO/device).
519 // Move back up a level.
520 if (ACE_OS::chdir (DIR_DOT_DOT
) == -1)
522 ACE_ERROR_RETURN ((LM_ERROR
,
523 "DRV_sweep_dirs: chdir "
524 ".. (from %C) failed\n",
533 DRV_add_include_path (ACE_CString
& include_path
,
543 const bool needToQuote
=
544 (('"' == *path
) || ACE_OS::strchr (path
, ' '));
545 const size_t pathLength
= ACE_OS::strlen (path
);
547 #if defined (ACE_WIN32)
555 // Eliminate possible enclosing quotes
556 // from the path, and since some compilers
557 // choke on double directory separators in
558 // paths, ensure that the path does not
559 // end with a directory slash.
561 ACE_CString (path
+ ('"' == *path
), // Skip leading Quote
563 - ('"' == *path
) // Don't count leading Quote
564 - ( (1uL < pathLength
) && // Don't count trailing Quote XOR directory
565 ('"' == path
[pathLength
- 1uL] ||
566 nativeDir
== path
[pathLength
- 1uL] ||
567 foreignDir
== path
[pathLength
- 1uL]
569 - ( (2uL < pathLength
) && // Don't count trailing Quote AND directory
570 '"' == path
[pathLength
- 1uL] &&
571 (nativeDir
== path
[pathLength
- 2uL] ||
572 foreignDir
== path
[pathLength
- 2uL]
576 if (suffix
!= nullptr)
578 if (!include_path
.length ()
579 && ((nativeDir
== *suffix
) || (foreignDir
== *suffix
)))
581 // Path is empty, don't add the
582 // suffix's leading directory separator.
586 if (include_path
.length ()
588 && (nativeDir
!= *suffix
)
589 && (foreignDir
!= *suffix
))
591 // Force a directory separator.
592 include_path
+= nativeDir
;
595 // Add the suffix string to the path,
596 // ensuring that foreign directory slashes
597 // are added as the native type.
598 for ( ; *suffix
!= '\0'; ++suffix
)
600 include_path
+= (foreignDir
== *suffix
)
606 // Build up the include string from the new path+suffix
607 ACE_CString
include_option ("-I\"", 2 + needToQuote
);
608 include_option
+= include_path
;
612 include_option
+= '"';
615 DRV_cpp_putarg (include_option
.c_str ());
617 idl_global
->add_include_path (include_path
.c_str (),
623 // Adds additional include paths, but after parse_args() has
624 // added user-defined include paths.
628 char idl_version_arg
[128];
629 ACE_OS::sprintf (idl_version_arg
, "-D__TAO_IDL_IDL_VERSION=%s",
630 idl_global
->idl_version_
.to_macro ());
631 DRV_cpp_putarg (idl_version_arg
);
633 DRV_cpp_putarg ("-D__TAO_IDL_FEATURES="
634 #ifdef TAO_IDL_FEATURES
637 "\"tao/idl_features.h\""
641 // Add include path for TAO_ROOT/orbsvcs.
642 char* TAO_ROOT
= ACE_OS::getenv ("TAO_ROOT");
644 ACE_CString include_path3
, include_path4
, include_path5
;
646 // When adding new dirs here don't forget to update
647 // FE_Utils::validate_orb_include accordingly.
648 if (TAO_ROOT
!= nullptr)
650 DRV_add_include_path (include_path3
,
657 // If TAO_ROOT isn't defined, assume it's under ACE_ROOT.
658 char* ACE_ROOT
= ACE_OS::getenv ("ACE_ROOT");
660 if (ACE_ROOT
!= nullptr)
662 DRV_add_include_path (include_path3
,
669 #if defined (TAO_IDL_INCLUDE_DIR)
670 DRV_add_include_path (include_path3
,
675 // If ACE_ROOT isn't defined either, there will already
676 // be a warning from DRV_preproc().
677 DRV_add_include_path (include_path3
,
681 #endif /* TAO_IDL_INCLUDE_DIR */
685 // Add include paths for CIAO_ROOT and CIAO_ROOT/ciao.
686 char* CIAO_ROOT
= ACE_OS::getenv ("CIAO_ROOT");
688 // When adding new dirs here don't forget to update
689 // FE_Utils::validate_orb_include accordingly.
690 if (CIAO_ROOT
!= nullptr)
692 DRV_add_include_path (include_path4
,
697 DRV_add_include_path (include_path5
,
702 DRV_add_include_path (include_path5
,
708 // Save path of current directory, in case
709 // the call to DRV_sweep_dirs()
710 // below is not a no-op - then the current
711 // working directory will
712 // have to be restored.
713 char cwd_path
[MAXPATHLEN
];
715 if (ACE_OS::getcwd (cwd_path
, sizeof (cwd_path
)) == nullptr)
717 ACE_ERROR ((LM_ERROR
,
718 "DRV_cpp_post_init: ACE_OS::getcwd failed\n"));
723 // If first arg is non-zero, adds an include path and filename
724 // for every IDL file found in all subdirectories. This is a
725 // no-op for most backends.
726 if (DRV_sweep_dirs (idl_global
->recursion_start (), "") == -1)
728 ACE_ERROR ((LM_ERROR
,
729 "DRV_cpp_post_init: DRV_sweep_dirs (%C) failed\n",
730 idl_global
->recursion_start ()));
735 // This is redundant for most backends, but not if the call to
736 // DRV_sweep_dirs() above is more than a no-op.
737 if (ACE_OS::chdir (cwd_path
) == -1)
739 ACE_ERROR ((LM_ERROR
,
740 "DRV_cpp_post_init: ACE_OS::chdir (%C) failed\n",
747 // Local/internal helper function.
750 // Advances the input char buffer to the first non-white
751 // space character, handles /**/ comments as well.
753 DRV_skip_over_white_spaces (const char *&input
)
757 // Skip the spaces, tabs, vertical-tabs and form feeds.
758 while (' ' == *input
||
766 // Skip any "/*...*/" inline comments
767 // (Note we can't cope with fully multi-line comments since we
768 // are scanning only single lines at a time here.)
771 // This is the first non-white space character (could be
778 // Wasn't the start of a comment so / was the first non-white space character.
782 // Skip over the contents of the comment (if we reach the end of the input
783 // line we have no option but to concider the comment closed, bummer).
786 // Looking for the closing "*/" characters
787 while ('*' != *++input
&& *input
)
790 while ('*' == *input
)
794 } while ('/' != *input
&& *input
);
802 return '\0'; // Reached end of line.
805 // Checks for and skips over #include, positions buffer
806 // at the leading quote character of the filename if
807 // #include is found.
809 DRV_find_include_filename (const char *&input
)
811 // Must have initial # character
812 if ('#' != DRV_skip_over_white_spaces (input
))
817 // Only want #include to match
818 const char *include_str
= "include";
820 if (*include_str
!= DRV_skip_over_white_spaces (++input
))
825 while (*++include_str
== *++input
&& *input
)
828 if (*include_str
|| !*input
)
830 // Not #include (or it ends before filename given).
834 // Next thing is finding the file that has been `#include'd. Skip
835 // over to the starting " or < character.
836 const char start_char
= DRV_skip_over_white_spaces (input
);
837 return ('"' == start_char
|| '<' == start_char
);
840 // We really need to know whether
841 // this line is a "#include ...". If
842 // so, we would like to separate the
843 // "file name" and keep that in the
844 // idl_global. We need them to produce
845 // "#include's in the stubs and
848 DRV_check_for_include (const char *buf
)
850 if (!DRV_find_include_filename (buf
))
855 // Skip over this leading " or < and
856 // copy the filename upto the
857 // closing " or > character.
860 end_char
= ('<' == start_char
) ? '>' : start_char
;
863 incl_file
[MAXPATHLEN
+ 1],
866 while (*buf
!= '\0' && *buf
!= end_char
)
868 // Put Microsoft-style pathnames into a canonical form.
869 if ('\\' == buf
[0] && '\\' == buf
[1])
876 if (fi
== incl_file
+ sizeof (incl_file
) - 1)
878 // Safety valve, filename given was too long!
884 const size_t len
= fi
- incl_file
;
888 return; // Null filename not allowed.
891 ACE_CString
const name_str (incl_file
);
892 ACE_CString
const simple ("orb.idl");
893 ACE_CString
const nix_path ("tao/orb.idl");
894 ACE_CString
const win_path ("tao\\orb.idl");
896 // Some backends pass this file through, others don't.
897 if (name_str
== simple
898 || name_str
== nix_path
899 || name_str
== win_path
)
901 if (idl_global
->pass_orb_idl ())
903 idl_global
->add_to_included_idl_files (incl_file
);
907 DRV_get_orb_idl_includes ();
910 // We have special lookup for orb.idl (TAO_ROOT/tao) that
911 // also kicks in for .pidl files. If one of the latter is
912 // included as a local name only, we add the 'tao/' prefix
913 // so the generated C++ include files will be correct.
914 else if ((5 <= len
&& !ACE_OS::strcmp (incl_file
+ len
- 5, ".pidl"))
915 && !ACE_OS::strchr (incl_file
, '/')
916 && !ACE_OS::strchr (incl_file
, '\\'))
918 ACE_CString
fixed_name ("tao/");
919 fixed_name
+= incl_file
;
921 idl_global
->add_to_included_idl_files (fixed_name
.c_str ());
925 idl_global
->add_to_included_idl_files (incl_file
);
929 // This method turns a line like '#include "a.idl"' into the
930 // line '#include <a.idl>'
932 DRV_convert_includes (char *buf
)
934 const char *input
= buf
;
936 if (!DRV_find_include_filename (input
) || '"' != *input
)
938 return; // Only interested in #include "" type
941 buf
= const_cast<char *> (input
);
943 // Find the closing '"' character.
944 char *open_quote
= buf
;
946 while ('"' != *++buf
&& *buf
!= '\0')
950 // Can't change to #include <> as it
951 // has a > character in the filename!
957 // Replace the quotes with angle brackets.
962 } // End of local/internal namespace
965 DRV_get_orb_idl_includes ()
967 static char const orb_idl
[] = "tao/orb.idl";
969 // Search for orb.idl in supplied include file search paths.
970 char const * directory
= nullptr;
971 FILE * fp
= FE_Utils::open_included_file (orb_idl
, directory
);
975 // Fall back on $TAO_ROOT/tao/orb.idl if orb.idl is not in the
977 ACE_CString
orb_idl_path (ACE_CString (idl_global
->tao_root ())
979 + ACE_CString (orb_idl
));
981 fp
= ACE_OS::fopen (orb_idl_path
.c_str (), "r");
985 ACE_ERROR ((LM_ERROR
,
986 "TAO_IDL: cannot open or find file: %C\n",
987 orb_idl_path
.c_str ()));
994 // Make sure the include directory containing orb.idl is passed
995 // to the preprocessor.
996 // This should go after user supplied include paths.
997 ACE_CString include_path_arg
;
998 DRV_add_include_path (include_path_arg
, directory
, "/tao", true);
1001 while (DRV_get_line (fp
))
1003 // Find the included .pidl files in orb.idl and add them to the
1004 // included IDL file list.
1005 DRV_check_for_include (drv_line
);
1008 ACE_OS::fclose (fp
);
1013 DRV_copy_input (FILE *fin
,
1016 const char *orig_filename
)
1020 ACE_ERROR ((LM_ERROR
,
1021 "%C: cannot open temp file \"%C\" for copying from \"%C\": %m\n",
1022 idl_global
->prog_name (),
1031 ACE_ERROR ((LM_ERROR
,
1032 "%C: cannot open input file\n",
1033 idl_global
->prog_name ()));
1038 #if !defined (ACE_WIN32)
1043 // Convert single \ into double \ otherwise MSVC++ pre-processor
1044 // gets awfully confused.
1045 char buf
[2*MAXPATHLEN
];
1048 for (const char *s
= orig_filename
; *s
!= 0; ++s
)
1064 #endif /* ! ACE_WIN32 */
1066 while (DRV_get_line (fin
))
1068 DRV_convert_includes (drv_line
);
1070 // Print the line to the temporary file.
1075 // We really need to know whether this line is a "#include
1076 // ...". If so, we would like to separate the "file name" and
1077 // keep that in the idl_global. We need them to produce
1078 // "#include's in the stubs and skeletons.
1079 DRV_check_for_include (drv_line
);
1082 // Close the temporary file.
1086 // Strip down a name to the last component,
1087 // i.e. everything after the last '/' or '\' character.
1089 DRV_stripped_name (char *fn
)
1099 l
= ACE_OS::strlen (n
);
1100 int slash_found
= 0;
1102 for (n
+= l
- 1; n
>= fn
&& !slash_found
; n
--)
1104 slash_found
= (*n
== '/' || *n
== '\\');
1117 // Pass input through preprocessor.
1119 DRV_pre_proc (const char *myfile
)
1121 // Check to see that the file is a normal file. If we don't and the file is a
1122 // directory, then the copy would be blank and any error message later might
1125 if (ACE_OS::stat (myfile
, &file_stat
) == -1)
1127 ACE_ERROR ((LM_ERROR
,
1128 "%C: ERROR: Unable to open file (stat) \"%C\": %m\n",
1129 idl_global
->prog_name (),
1133 else if ((file_stat
.st_mode
& S_IFREG
) != S_IFREG
)
1135 ACE_ERROR ((LM_ERROR
,
1136 "%C: ERROR: This is not a regular file: \"%C\"\n",
1137 idl_global
->prog_name (),
1142 const char* tmpdir
= idl_global
->temp_dir ();
1143 static const char temp_file_extension
[] = ".cpp";
1145 static char const tao_idlf_template
[] = "tao-idlf_XXXXXX";
1146 static char const tao_idli_template
[] = "tao-idli_XXXXXX";
1149 ACE_OS::strlen (tmpdir
) + sizeof (temp_file_extension
);
1151 // Prevent a buffer overrun.
1152 if (tlen
+ sizeof (tao_idlf_template
) > sizeof (tmp_file
)
1153 || tlen
+ sizeof (tao_idli_template
) > sizeof (tmp_ifile
))
1155 ACE_ERROR ((LM_ERROR
,
1156 "%C: temporary path/filename length is greater than "
1157 "length allowed by platform\n",
1158 idl_global
->prog_name ()));
1163 ACE_OS::strcpy (tmp_file
, tmpdir
);
1164 ACE_OS::strcpy (tmp_ifile
, tmpdir
);
1166 // Append temporary filename template to temporary directory.
1167 ACE_OS::strcat (tmp_file
, tao_idlf_template
);
1168 ACE_OS::strcat (tmp_ifile
, tao_idli_template
);
1170 ACE_HANDLE
const ti_fd
= ACE_OS::mkstemp (tmp_ifile
);
1172 if (ti_fd
== ACE_INVALID_HANDLE
)
1174 ACE_ERROR ((LM_ERROR
,
1175 "%C: Unable to create temporary file \"%C\": %m\n",
1176 idl_global
->prog_name (),
1182 ACE_HANDLE
const tf_fd
= ACE_OS::mkstemp (tmp_file
);
1184 if (tf_fd
== ACE_INVALID_HANDLE
)
1186 ACE_ERROR ((LM_ERROR
,
1187 "%C: Unable to create temporary file \"%C\": %m\n",
1188 idl_global
->prog_name (),
1191 (void) ACE_OS::unlink (tmp_ifile
);
1195 char tmp_cpp_file
[MAXPATHLEN
+ 1] = { 0 };
1196 char tmp_cpp_ifile
[MAXPATHLEN
+ 1] = { 0 };
1198 // Append C++ source file extension. Temporary files will be renamed
1199 // to these filenames.
1200 ACE_OS::strcpy (tmp_cpp_file
, tmp_file
);
1201 ACE_OS::strcpy (tmp_cpp_ifile
, tmp_ifile
);
1202 ACE_OS::strcat (tmp_cpp_file
, temp_file_extension
);
1203 ACE_OS::strcat (tmp_cpp_ifile
, temp_file_extension
);
1205 char * const t_file
= tmp_cpp_file
;
1206 char * const t_ifile
= tmp_cpp_ifile
;
1208 ACE_OS::close (tf_fd
);
1210 // Rename temporary files so that they have extensions accepted
1211 // by the preprocessor.
1212 FILE * const file
= ACE_OS::fopen (myfile
, "r");
1213 if (file
== nullptr)
1215 ACE_ERROR ((LM_ERROR
,
1216 "%C: ERROR: Unable to open file (fopen) \"%C\": %m\n",
1217 idl_global
->prog_name (),
1219 (void) ACE_OS::unlink (tmp_ifile
);
1220 (void) ACE_OS::unlink (tmp_file
);
1224 DRV_copy_input (file
,
1225 ACE_OS::fdopen (ti_fd
, ACE_TEXT("w")),
1228 ACE_OS::fclose (file
);
1230 UTL_String
*utl_string
= nullptr;
1232 ACE_NEW (utl_string
,
1233 UTL_String (myfile
, true));
1235 idl_global
->set_main_filename (utl_string
);
1237 ACE_Auto_String_Free
safety (ACE_OS::strdup (myfile
));
1239 UTL_String
*stripped_tmp
= nullptr;
1240 ACE_NEW (stripped_tmp
,
1241 UTL_String (DRV_stripped_name (safety
.get ()), true));
1243 idl_global
->set_stripped_filename (stripped_tmp
);
1245 UTL_String
*real_tmp
= nullptr;
1247 UTL_String (t_ifile
, true));
1249 idl_global
->set_real_filename (real_tmp
);
1251 // We use ACE instead of the (low level) fork facilities, this also
1253 ACE_Process process
;
1255 DRV_cpp_expand_output_arg (t_file
);
1256 DRV_cpp_putarg (t_ifile
);
1257 DRV_cpp_putarg (nullptr); // Null terminate the DRV_arglist.
1259 // For complex builds, the default
1260 // command line buffer size of 1024
1261 // is often not enough. We determine
1262 // the required space and arg nr
1263 // dynamically here.
1264 ACE_Process_Options
cpp_options (true, // Inherit environment.
1265 DRV_cpp_calc_total_argsize (),
1270 if (cpp_options
.command_line (DRV_arglist
) != 0)
1272 ACE_ERROR ((LM_ERROR
,
1273 ACE_TEXT ("%C: command line processing \"%s\" failed\n"),
1274 idl_global
->prog_name (),
1277 (void) ACE_OS::unlink (tmp_ifile
);
1278 (void) ACE_OS::unlink (tmp_file
);
1282 // Rename temporary files so that they have extensions accepted
1283 // by the preprocessor. Renaming is (supposed to be) an atomic
1284 // operation so we shouldn't be susceptible to attack.
1285 if (ACE_OS::rename (tmp_file
, t_file
) != 0)
1287 ACE_ERROR ((LM_ERROR
,
1288 "%C: Unable to rename temporary "
1289 "file \"%C\" to \"%C\": %m\n",
1290 idl_global
->prog_name (),
1295 (void) ACE_OS::unlink (tmp_ifile
);
1296 (void) ACE_OS::unlink (tmp_file
);
1300 if (ACE_OS::rename (tmp_ifile
, t_ifile
) != 0)
1302 ACE_ERROR ((LM_ERROR
,
1303 "%C: Unable to rename temporary "
1304 "file \"%C\" to \"%C\": %m\n",
1305 idl_global
->prog_name (),
1309 (void) ACE_OS::unlink (tmp_ifile
);
1310 (void) ACE_OS::unlink (t_file
);
1314 // Remove any existing output file.
1315 (void) ACE_OS::unlink (t_file
);
1317 ACE_HANDLE fd
= ACE_INVALID_HANDLE
;
1319 if (output_arg_format
== nullptr)
1321 // If the following open() fails, then we're either being hit with a
1322 // symbolic link attack, or another process opened the file before
1324 fd
= ACE_OS::open (t_file
,
1325 O_WRONLY
| O_CREAT
| O_EXCL
,
1326 ACE_DEFAULT_FILE_PERMS
);
1328 if (fd
== ACE_INVALID_HANDLE
)
1330 ACE_ERROR ((LM_ERROR
,
1331 "%C: cannot open temp file"
1332 " \"%C\" for writing: %m\n",
1333 idl_global
->prog_name (),
1336 (void) ACE_OS::unlink (t_file
);
1337 (void) ACE_OS::unlink (t_ifile
);
1341 if (cpp_options
.set_handles (ACE_INVALID_HANDLE
, fd
) == -1)
1343 ACE_ERROR ((LM_ERROR
, "%C: cannot set stdout for child process: %m\n",
1344 idl_global
->prog_name ()));
1350 if (idl_global
->compile_flags () & IDL_CF_INFORMATIVE
)
1352 ACE_DEBUG ((LM_DEBUG
, "%C: spawning: %s\n",
1353 idl_global
->prog_name (),
1354 cpp_options
.command_line_buf ()));
1357 if (process
.spawn (cpp_options
) == ACE_INVALID_PID
)
1359 ACE_ERROR ((LM_ERROR
,
1360 "%C: spawn of \"%s\" failed\n",
1361 idl_global
->prog_name (),
1365 (void) ACE_OS::unlink (t_file
);
1366 (void) ACE_OS::unlink (t_ifile
);
1370 if (fd
!= ACE_INVALID_HANDLE
)
1372 // Close the output file on the parent process.
1373 if (ACE_OS::close (fd
) == -1)
1375 ACE_ERROR ((LM_ERROR
,
1376 "%C: cannot close temp file \"%C\" on parent: %m\n",
1377 idl_global
->prog_name (),
1380 (void) ACE_OS::unlink (t_file
);
1381 (void) ACE_OS::unlink (t_ifile
);
1386 // Remove the null termination and the
1387 // input file from the DRV_arglist,
1388 // the next file will the previous args.
1391 const_cast<ACE_TCHAR
*> (DRV_arglist
[DRV_argcount
]));
1392 DRV_arglist
[DRV_argcount
] = nullptr;
1393 ACE_exitcode status
= 0;
1395 if (process
.wait (&status
) == ACE_INVALID_PID
)
1397 ACE_ERROR ((LM_ERROR
,
1398 "%C: wait for child process failed\n",
1399 idl_global
->prog_name ()));
1401 (void) ACE_OS::unlink (t_file
);
1402 (void) ACE_OS::unlink (t_ifile
);
1406 if (WIFEXITED ((status
)))
1408 // Child terminated normally?
1409 if (WEXITSTATUS ((status
)) != 0)
1411 errno
= WEXITSTATUS ((status
));
1413 ACE_ERROR ((LM_ERROR
,
1414 "%C: preprocessor \"%s\" "
1415 "returned with an error\n",
1416 idl_global
->prog_name (),
1419 (void) ACE_OS::unlink (t_file
);
1420 (void) ACE_OS::unlink (t_ifile
);
1426 // Child didn't call exit(); perhaps it received a signal?
1429 ACE_ERROR ((LM_ERROR
,
1430 "%C: preprocessor \"%s\" appears "
1431 "to have been interrupted\n",
1432 idl_global
->prog_name (),
1435 (void) ACE_OS::unlink (t_file
);
1436 (void) ACE_OS::unlink (t_ifile
);
1439 // TODO: Manage problems in the
1440 // pre-processor, in the previous
1441 // version the current process
1442 // would exit if the pre-processor
1443 // returned with error.
1444 FILE * const yyin
= ACE_OS::fopen (t_file
, "r");
1446 if (yyin
== nullptr)
1448 ACE_ERROR ((LM_ERROR
,
1449 "%C: Could not open cpp "
1450 "output file \"%C\": %m\n",
1451 idl_global
->prog_name (),
1454 (void) ACE_OS::unlink (t_file
);
1455 (void) ACE_OS::unlink (t_ifile
);
1461 if (idl_global
->compile_flags () & IDL_CF_ONLY_PREPROC
)
1463 FILE *preproc
= ACE_OS::fopen (t_file
, "r");
1464 char buffer
[ACE_MAXLOGMSGLEN
];
1467 if (preproc
== nullptr)
1469 ACE_ERROR ((LM_ERROR
,
1470 "%C: Could not open cpp "
1471 "output file \"%C\": %m\n",
1472 idl_global
->prog_name (),
1475 (void) ACE_OS::unlink (t_file
);
1476 (void) ACE_OS::unlink (t_ifile
);
1480 // ACE_DEBUG sends to stderr - we want stdout for this dump
1481 // of the preprocessor output. So we modify the singleton that
1482 // was created in this process. Since IDL_CF_ONLY_PREPROC causes
1483 // an (almost) immediate exit below, we don't have to restore
1484 // the singleton's default parameters.
1485 ACE_Log_Msg
*out
= ACE_Log_Msg::instance ();
1486 out
->msg_ostream (&cout
);
1487 out
->clr_flags (ACE_Log_Msg::STDERR
);
1488 out
->set_flags (ACE_Log_Msg::OSTREAM
);
1490 while ((bytes
= ACE_OS::fread (buffer
,
1492 ACE_MAXLOGMSGLEN
- 1,
1497 ACE_DEBUG ((LM_DEBUG
, buffer
));
1500 ACE_OS::fclose (preproc
);
1503 if (ACE_OS::unlink (t_ifile
) == -1)
1505 ACE_ERROR ((LM_ERROR
,
1506 "%C: Could not remove cpp "
1507 "input file \"%C\": %m\n",
1508 idl_global
->prog_name (),
1514 if (ACE_OS::unlink (t_file
) == -1)
1516 ACE_ERROR ((LM_ERROR
,
1517 "%C: Could not remove cpp "
1518 "output file \"%C\": %m\n",
1519 idl_global
->prog_name (),