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
] = { 0 };
97 static char const * output_arg_format
= 0;
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
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 (),
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
!= 0)
214 ACE::strdelete (const_cast<ACE_TCHAR
*> (
215 DRV_arglist
[output_arg_index
]));
216 DRV_arglist
[output_arg_index
] = 0;
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
] != 0)
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;
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
== 0)
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");
351 DRV_add_include_path (include_path1
,
356 DRV_add_include_path (include_path2
,
363 char* ACE_ROOT
= ACE_OS::getenv ("ACE_ROOT");
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")) != 0
412 && output_arg_format
== 0)
415 ACE::strnew (ACE_TEXT_ALWAYS_CHAR (platform_arglist
[i
]));
416 output_arg_index
= DRV_argcount
;
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.
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
] = "";
453 for (ACE_DIRENT
*dir_entry
; (dir_entry
= dir
.read ()) != 0;)
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
);
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]
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.
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");
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.
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
)) == 0)
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
= 0;
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");
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
= 0;
1232 #if defined (ACE_OPENVMS)
1234 char main_abspath
[MAXPATHLEN
] = "";
1235 char trans_path
[MAXPATHLEN
] = "";
1236 char *main_fullpath
=
1237 ACE_OS::realpath (IDL_GlobalData::translateName (myfile
, trans_path
),
1240 if (main_fullpath
== 0)
1242 ACE_ERROR ((LM_ERROR
,
1243 ACE_TEXT ("Unable to construct full file pathname\n")));
1245 (void) ACE_OS::unlink (tmp_ifile
);
1246 (void) ACE_OS::unlink (tmp_file
);
1250 ACE_NEW (utl_string
,
1251 UTL_String (main_fullpath
, true));
1253 idl_global
->set_main_filename (utl_string
);
1256 ACE_NEW (utl_string
,
1257 UTL_String (myfile
, true));
1259 idl_global
->set_main_filename (utl_string
);
1262 ACE_Auto_String_Free
safety (ACE_OS::strdup (myfile
));
1264 UTL_String
*stripped_tmp
= 0;
1265 ACE_NEW (stripped_tmp
,
1266 UTL_String (DRV_stripped_name (safety
.get ()), true));
1268 idl_global
->set_stripped_filename (stripped_tmp
);
1270 UTL_String
*real_tmp
= 0;
1272 UTL_String (t_ifile
, true));
1274 idl_global
->set_real_filename (real_tmp
);
1276 // We use ACE instead of the (low level) fork facilities, this also
1278 ACE_Process process
;
1280 DRV_cpp_expand_output_arg (t_file
);
1281 DRV_cpp_putarg (t_ifile
);
1282 DRV_cpp_putarg (0); // Null terminate the DRV_arglist.
1284 // For complex builds, the default
1285 // command line buffer size of 1024
1286 // is often not enough. We determine
1287 // the required space and arg nr
1288 // dynamically here.
1289 ACE_Process_Options
cpp_options (1, // Inherit environment.
1290 DRV_cpp_calc_total_argsize (),
1295 if (cpp_options
.command_line (DRV_arglist
) != 0)
1297 ACE_ERROR ((LM_ERROR
,
1298 ACE_TEXT ("%C: command line processing \"%s\" failed\n"),
1299 idl_global
->prog_name (),
1302 (void) ACE_OS::unlink (tmp_ifile
);
1303 (void) ACE_OS::unlink (tmp_file
);
1307 // Rename temporary files so that they have extensions accepted
1308 // by the preprocessor. Renaming is (supposed to be) an atomic
1309 // operation so we shouldn't be susceptible to attack.
1310 if (ACE_OS::rename (tmp_file
, t_file
) != 0)
1312 ACE_ERROR ((LM_ERROR
,
1313 "%C: Unable to rename temporary "
1314 "file \"%C\" to \"%C\": %m\n",
1315 idl_global
->prog_name (),
1320 (void) ACE_OS::unlink (tmp_ifile
);
1321 (void) ACE_OS::unlink (tmp_file
);
1325 if (ACE_OS::rename (tmp_ifile
, t_ifile
) != 0)
1327 ACE_ERROR ((LM_ERROR
,
1328 "%C: Unable to rename temporary "
1329 "file \"%C\" to \"%C\": %m\n",
1330 idl_global
->prog_name (),
1334 (void) ACE_OS::unlink (tmp_ifile
);
1335 (void) ACE_OS::unlink (t_file
);
1339 // Remove any existing output file.
1340 (void) ACE_OS::unlink (t_file
);
1342 ACE_HANDLE fd
= ACE_INVALID_HANDLE
;
1344 if (output_arg_format
== 0)
1346 // If the following open() fails, then we're either being hit with a
1347 // symbolic link attack, or another process opened the file before
1349 #if defined (ACE_OPENVMS)
1350 //FUZZ: disable check_for_lack_ACE_OS
1351 fd
= ::open (t_file
, O_WRONLY
| O_CREAT
| O_EXCL
,
1352 ACE_DEFAULT_FILE_PERMS
,
1353 "shr=get,put,upd", "ctx=rec", "fop=dfw");
1354 //FUZZ: enable check_for_lack_ACE_OS
1356 fd
= ACE_OS::open (t_file
,
1357 O_WRONLY
| O_CREAT
| O_EXCL
,
1358 ACE_DEFAULT_FILE_PERMS
);
1361 if (fd
== ACE_INVALID_HANDLE
)
1363 ACE_ERROR ((LM_ERROR
,
1364 "%C: cannot open temp file"
1365 " \"%C\" for writing: %m\n",
1366 idl_global
->prog_name (),
1369 (void) ACE_OS::unlink (t_file
);
1370 (void) ACE_OS::unlink (t_ifile
);
1374 if (cpp_options
.set_handles (ACE_INVALID_HANDLE
, fd
) == -1)
1376 ACE_ERROR ((LM_ERROR
, "%C: cannot set stdout for child process: %m\n",
1377 idl_global
->prog_name ()));
1383 if (idl_global
->compile_flags () & IDL_CF_INFORMATIVE
)
1385 ACE_DEBUG ((LM_DEBUG
, "%C: spawning: %s\n",
1386 idl_global
->prog_name (),
1387 cpp_options
.command_line_buf ()));
1390 if (process
.spawn (cpp_options
) == ACE_INVALID_PID
)
1392 ACE_ERROR ((LM_ERROR
,
1393 "%C: spawn of \"%s\" failed\n",
1394 idl_global
->prog_name (),
1398 (void) ACE_OS::unlink (t_file
);
1399 (void) ACE_OS::unlink (t_ifile
);
1403 if (fd
!= ACE_INVALID_HANDLE
)
1405 // Close the output file on the parent process.
1406 if (ACE_OS::close (fd
) == -1)
1408 ACE_ERROR ((LM_ERROR
,
1409 "%C: cannot close temp file \"%C\" on parent: %m\n",
1410 idl_global
->prog_name (),
1413 (void) ACE_OS::unlink (t_file
);
1414 (void) ACE_OS::unlink (t_ifile
);
1419 // Remove the null termination and the
1420 // input file from the DRV_arglist,
1421 // the next file will the previous args.
1424 const_cast<ACE_TCHAR
*> (DRV_arglist
[DRV_argcount
]));
1425 DRV_arglist
[DRV_argcount
] = 0;
1426 ACE_exitcode status
= 0;
1428 if (process
.wait (&status
) == ACE_INVALID_PID
)
1430 ACE_ERROR ((LM_ERROR
,
1431 "%C: wait for child process failed\n",
1432 idl_global
->prog_name ()));
1434 (void) ACE_OS::unlink (t_file
);
1435 (void) ACE_OS::unlink (t_ifile
);
1439 if (WIFEXITED ((status
)))
1441 // Child terminated normally?
1442 if (WEXITSTATUS ((status
)) != 0)
1444 errno
= WEXITSTATUS ((status
));
1446 ACE_ERROR ((LM_ERROR
,
1447 "%C: preprocessor \"%s\" "
1448 "returned with an error\n",
1449 idl_global
->prog_name (),
1452 (void) ACE_OS::unlink (t_file
);
1453 (void) ACE_OS::unlink (t_ifile
);
1459 // Child didn't call exit(); perhaps it received a signal?
1462 ACE_ERROR ((LM_ERROR
,
1463 "%C: preprocessor \"%s\" appears "
1464 "to have been interrupted\n",
1465 idl_global
->prog_name (),
1468 (void) ACE_OS::unlink (t_file
);
1469 (void) ACE_OS::unlink (t_ifile
);
1472 // TODO: Manage problems in the
1473 // pre-processor, in the previous
1474 // version the current process
1475 // would exit if the pre-processor
1476 // returned with error.
1478 #if defined (ACE_OPENVMS)
1479 cpp_options
.release_handles();
1482 FILE * const yyin
= ACE_OS::fopen (t_file
, "r");
1486 ACE_ERROR ((LM_ERROR
,
1487 "%C: Could not open cpp "
1488 "output file \"%C\": %m\n",
1489 idl_global
->prog_name (),
1492 (void) ACE_OS::unlink (t_file
);
1493 (void) ACE_OS::unlink (t_ifile
);
1499 if (idl_global
->compile_flags () & IDL_CF_ONLY_PREPROC
)
1501 FILE *preproc
= ACE_OS::fopen (t_file
, "r");
1502 char buffer
[ACE_MAXLOGMSGLEN
];
1507 ACE_ERROR ((LM_ERROR
,
1508 "%C: Could not open cpp "
1509 "output file \"%C\": %m\n",
1510 idl_global
->prog_name (),
1513 (void) ACE_OS::unlink (t_file
);
1514 (void) ACE_OS::unlink (t_ifile
);
1518 // ACE_DEBUG sends to stderr - we want stdout for this dump
1519 // of the preprocessor output. So we modify the singleton that
1520 // was created in this process. Since IDL_CF_ONLY_PREPROC causes
1521 // an (almost) immediate exit below, we don't have to restore
1522 // the singleton's default parameters.
1523 ACE_Log_Msg
*out
= ACE_Log_Msg::instance ();
1524 out
->msg_ostream (&cout
);
1525 out
->clr_flags (ACE_Log_Msg::STDERR
);
1526 out
->set_flags (ACE_Log_Msg::OSTREAM
);
1528 while ((bytes
= ACE_OS::fread (buffer
,
1530 ACE_MAXLOGMSGLEN
- 1,
1535 ACE_DEBUG ((LM_DEBUG
, buffer
));
1538 ACE_OS::fclose (preproc
);
1541 if (ACE_OS::unlink (t_ifile
) == -1)
1543 ACE_ERROR ((LM_ERROR
,
1544 "%C: Could not remove cpp "
1545 "input file \"%C\": %m\n",
1546 idl_global
->prog_name (),
1552 if (ACE_OS::unlink (t_file
) == -1)
1554 ACE_ERROR ((LM_ERROR
,
1555 "%C: Could not remove cpp "
1556 "output file \"%C\": %m\n",
1557 idl_global
->prog_name (),