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_Manager.h"
77 #include "ace/SString.h"
78 #include "ace/Env_Value_T.h"
81 #include "ace/Dirent.h"
82 #include "ace/OS_NS_sys_stat.h"
83 #include "ace/Truncate.h"
85 // FUZZ: disable check_for_streams_include
86 #include "ace/streams.h"
88 #include "ace/OS_NS_stdio.h"
89 #include "ace/OS_NS_unistd.h"
90 #include "ace/OS_NS_fcntl.h"
91 #include "ace/OS_NS_sys_stat.h"
93 // Storage for preprocessor args.
94 unsigned long const DRV_MAX_ARGCOUNT
= 1024;
95 unsigned long DRV_argcount
= 0;
96 ACE_TCHAR
const * DRV_arglist
[DRV_MAX_ARGCOUNT
] = { 0 };
98 static char const * output_arg_format
= 0;
99 static long output_arg_index
= 0;
101 ACE_TCHAR
const TCHAR_DIR_DOT
[] = ACE_TEXT(".");
103 #if defined (ACE_HAS_TCHAR_DIRENT)
104 // ACE_TCHAR const DIR_DOT[] = ACE_TEXT(".");
105 ACE_TCHAR
const DIR_DOT_DOT
[] = ACE_TEXT("..");
107 // char const DIR_DOT[] = ".";
108 char const DIR_DOT_DOT
[] = "..";
109 #endif /* ACE_HAS_TCHAR_DIRENT */
112 static char tmp_file
[MAXPATHLEN
+ 1] = { 0 };
113 static char tmp_ifile
[MAXPATHLEN
+ 1] = { 0 };
115 // Lines can be 1024 chars long intially -
116 // it will expand as required.
117 #define LINEBUF_SIZE 1024
119 static size_t drv_line_size
= LINEBUF_SIZE
+ 1;
121 // Push the new CPP location if we got a -Yp argument.
123 DRV_cpp_new_location (char const * new_loc
)
125 ACE::strdelete (const_cast<ACE_TCHAR
*> (DRV_arglist
[0]));
127 ACE::strnew (ACE_TEXT_CHAR_TO_TCHAR (new_loc
));
130 // Push an argument into the DRV_arglist.
132 DRV_cpp_putarg (const char *str
)
134 if (DRV_argcount
>= DRV_MAX_ARGCOUNT
)
136 ACE_ERROR ((LM_ERROR
,
137 "%C: More than %d arguments to preprocessor\n",
138 idl_global
->prog_name (),
147 bool allocate_error
= false;
150 const char *const first_quote
= ACE_OS::strchr (str
, '"');
153 // Escape Doublequotes on Windows
155 size_t quote_count
= 0;
156 for (const char *quote
= first_quote
; quote
; quote
= ACE_OS::strchr (quote
, '"'))
162 ACE_NEW_NORETURN (replace
, char[ACE_OS::strlen (str
) + quote_count
+ 1]);
163 allocate_error
= !replace
;
167 for (const char *from
= str
; *from
; ++from
)
181 if (ACE_OS::strchr (str
, ' '))
183 ACE_NEW_NORETURN (replace
, char[ACE_OS::strlen (str
) + 3]);
184 allocate_error
= !replace
;
188 ACE_OS::strcpy (replace
+ 1, str
);
189 ACE_OS::strcat (replace
, "\"");
195 idl_global
->err()->misc_error ("DRV_cpp_putarg failed to allocate memory for argument!");
200 DRV_arglist
[DRV_argcount
++] = ACE::strnew (ACE_TEXT_CHAR_TO_TCHAR (replace
? replace
: str
));
209 // Expand the output argument with the given filename.
211 DRV_cpp_expand_output_arg (const char *filename
)
213 if (output_arg_format
!= 0)
215 ACE::strdelete (const_cast<ACE_TCHAR
*> (
216 DRV_arglist
[output_arg_index
]));
217 DRV_arglist
[output_arg_index
] = 0;
219 ACE_NEW (DRV_arglist
[output_arg_index
],
220 ACE_TCHAR
[ACE_OS::strlen (output_arg_format
)
221 + ACE_OS::strlen (filename
)
224 ACE_OS::sprintf (const_cast<ACE_TCHAR
*> (
225 DRV_arglist
[output_arg_index
]),
226 ACE_TEXT_CHAR_TO_TCHAR (output_arg_format
),
227 ACE_TEXT_CHAR_TO_TCHAR (filename
));
231 // calculate the total size of all commandline arguments
233 DRV_cpp_calc_total_argsize(void)
235 unsigned long size
= 0;
236 unsigned long ix
= 0;
237 while (DRV_arglist
[ix
] != 0)
239 size
+= ACE_Utils::truncate_cast
<unsigned long> (ACE_OS::strlen (DRV_arglist
[ix
]) + 1);
245 // Get a line from stdin.
247 DRV_get_line (FILE *file
)
249 char *line
= ACE_OS::fgets (drv_line
,
250 ACE_Utils::truncate_cast
<int> (drv_line_size
),
252 if (!line
|| (!*line
&& feof (file
)))
254 // End of file, nothing else read in.
260 // Check for line continuation escape...
261 size_t len
= ACE_OS::strlen (drv_line
);
263 '\n' == drv_line
[len
-1] &&
264 '\\' == drv_line
[len
-2] )
266 // This is a "false" end-of-line, remove token
268 drv_line
[len
]= '\0';
271 // Check for end-of-line
272 if (len
&& '\n' == drv_line
[len
-1])
274 // Replace the end-of-line with a null
275 drv_line
[len
-1] = '\0';
279 // Need to continue to read more of this line in,
280 // is there enough space left in the buffer?
281 if (drv_line_size
- len
< 10)
283 // Create a bigger buffer
284 size_t temp_size
= drv_line_size
* 2;
286 ACE_NEW_RETURN (temp
, char [temp_size
], false);
287 ACE_OS::strcpy (temp
, drv_line
);
290 drv_line_size
= temp_size
;
293 line
= ACE_OS::fgets (drv_line
+ len
,
294 ACE_Utils::truncate_cast
<int> (drv_line_size
- len
),
296 } while (line
&& *line
);
301 // Initialize the cpp argument list.
305 // Create the line buffer.
306 // (JP) Deleting this at the end or DRV_pre_proc() causes
307 // Purify to output a Freeing Mismatched Memory warning.
308 // When it is not deleted (currently the case) there is no
309 // memory leak reported by Purify. I don't know why.
311 char [drv_line_size
]);
313 char const * const cpp_loc
= FE_get_cpp_loc_from_env ();
314 DRV_cpp_putarg (cpp_loc
);
316 // Add an option to the IDL compiler to make the TAO version
317 // available to the user. A XX.YY.ZZ release gets
318 // version 0xXXYYZZ, for example, 5.1.14 gets 0x050114.
319 char version_option
[128];
320 ACE_OS::sprintf (version_option
,
321 "-D__TAO_IDL=0x%2.2d%2.2d%2.2d",
326 DRV_cpp_putarg (version_option
);
327 DRV_cpp_putarg ("-I.");
329 const char *platform_cpp_args
=
330 FE_get_cpp_args_from_env ();
332 if (platform_cpp_args
== 0)
334 // If no cpp flag was defined by the user, we define some
335 // platform specific flags here.
337 #if defined (TAO_IDL_PREPROCESSOR_ARGS)
338 platform_cpp_args
= TAO_IDL_PREPROCESSOR_ARGS
;
339 #elif defined (ACE_CC_PREPROCESSOR_ARGS)
340 platform_cpp_args
= ACE_CC_PREPROCESSOR_ARGS
;
342 platform_cpp_args
= "-E";
343 #endif /* TAO_IDL_PREPROCESSOR_ARGS */
345 // So we can find OMG IDL files, such as `orb.idl'.
346 ACE_CString include_path1
, include_path2
;
348 char* TAO_ROOT
= ACE_OS::getenv ("TAO_ROOT");
352 DRV_add_include_path (include_path1
,
357 DRV_add_include_path (include_path2
,
364 char* ACE_ROOT
= ACE_OS::getenv ("ACE_ROOT");
368 DRV_add_include_path (include_path1
,
373 DRV_add_include_path (include_path2
,
380 #if defined (TAO_IDL_INCLUDE_DIR)
381 // TAO_IDL_INCLUDE_DIR may be in quotes,
382 // e.g. "/usr/local/include/tao"
383 // We deal with a case like this below ...
384 DRV_add_include_path (include_path1
,
388 DRV_add_include_path (include_path2
,
393 DRV_add_include_path (include_path1
,
397 #endif /* TAO_IDL_INCLUDE_DIR */
401 idl_global
->tao_root (include_path1
.c_str ());
404 // Add any flags in platform_cpp_args to cpp's DRV_arglist.
405 ACE_ARGV
platform_arglist (
406 ACE_TEXT_CHAR_TO_TCHAR (platform_cpp_args
));
408 for (int i
= 0; i
< platform_arglist
.argc (); ++i
)
410 // Check for an argument that specifies
411 // the preprocessor's output file.
412 if (ACE_OS::strstr (platform_arglist
[i
], ACE_TEXT ("%s")) != 0
413 && output_arg_format
== 0)
416 ACE::strnew (ACE_TEXT_ALWAYS_CHAR (platform_arglist
[i
]));
417 output_arg_index
= DRV_argcount
;
422 DRV_cpp_putarg (ACE_TEXT_ALWAYS_CHAR (platform_arglist
[i
]));
428 DRV_sweep_dirs (const char *rel_path
,
429 const char *base_path
)
431 // Zero rel_path means we're not using this option, and
432 // so we become a no-op.
438 if (ACE_OS::chdir (rel_path
) == -1)
440 ACE_ERROR_RETURN ((LM_ERROR
,
441 "DRV_sweep_dirs: chdir %C failed\n",
446 ACE_Dirent
dir (TCHAR_DIR_DOT
);
447 ACE_CString
bname (base_path
);
448 bname
+= (bname
.length () > 0 ? "/" : "");
450 bool include_added
= false;
451 char abspath
[MAXPATHLEN
] = "";
454 for (ACE_DIRENT
*dir_entry
; (dir_entry
= dir
.read ()) != 0;)
456 // Skip the ".." and "." files in each directory.
457 if (ACE::isdotdir (dir_entry
->d_name
) == true)
462 #if defined (ACE_HAS_TCHAR_DIRENT)
463 ACE_CString
lname (ACE_TEXT_ALWAYS_CHAR (dir_entry
->d_name
));
465 ACE_CString
lname (dir_entry
->d_name
);
469 if (ACE_OS::lstat (lname
.c_str (), &stat_buf
) == -1)
471 ACE_ERROR_RETURN ((LM_ERROR
,
472 "DRV_sweep_dirs: ACE_OS::lstat"
480 switch (stat_buf
.st_mode
& S_IFMT
)
482 case S_IFREG
: // Either a regular file or an executable.
483 len
= lname
.length ();
485 if (len
> 4 && lname
.substr (len
- 4) == ".idl")
489 ACE_CString
incl_arg ("-I");
491 DRV_cpp_putarg (incl_arg
.c_str ());
492 idl_global
->add_rel_include_path (bname
.c_str ());
493 full_path
= ACE_OS::realpath ("", abspath
);
497 idl_global
->add_include_path (full_path
,
501 include_added
= true;
504 ACE_CString
fname (bname
);
507 DRV_push_file (fname
.c_str ());
511 case S_IFDIR
: // Subdirectory.
512 DRV_sweep_dirs (lname
.c_str (), bname
.c_str ());
514 case S_IFLNK
: // Either a file link or directory link.
515 default: // Some other type of file (PIPE/FIFO/device).
520 // Move back up a level.
521 if (ACE_OS::chdir (DIR_DOT_DOT
) == -1)
523 ACE_ERROR_RETURN ((LM_ERROR
,
524 "DRV_sweep_dirs: chdir "
525 ".. (from %C) failed\n",
534 DRV_add_include_path (ACE_CString
& include_path
,
544 const bool needToQuote
=
545 (('"' == *path
) || ACE_OS::strchr (path
, ' '));
546 const size_t pathLength
= ACE_OS::strlen (path
);
548 #if defined (ACE_WIN32)
556 // Eliminate possible enclosing quotes
557 // from the path, and since some compilers
558 // choke on double directory separators in
559 // paths, ensure that the path does not
560 // end with a directory slash.
562 ACE_CString (path
+ ('"' == *path
), // Skip leading Quote
564 - ('"' == *path
) // Don't count leading Quote
565 - ( (1uL < pathLength
) && // Don't count trailing Quote XOR directory
566 ('"' == path
[pathLength
- 1uL] ||
567 nativeDir
== path
[pathLength
- 1uL] ||
568 foreignDir
== path
[pathLength
- 1uL]
570 - ( (2uL < pathLength
) && // Don't count trailing Quote AND directory
571 '"' == path
[pathLength
- 1uL] &&
572 (nativeDir
== path
[pathLength
- 2uL] ||
573 foreignDir
== path
[pathLength
- 2uL]
579 if (!include_path
.length ()
580 && ((nativeDir
== *suffix
) || (foreignDir
== *suffix
)))
582 // Path is empty, don't add the
583 // suffix's leading directory separator.
587 if (include_path
.length ()
589 && (nativeDir
!= *suffix
)
590 && (foreignDir
!= *suffix
))
592 // Force a directory separator.
593 include_path
+= nativeDir
;
596 // Add the suffix string to the path,
597 // ensuring that foreign directory slashes
598 // are added as the native type.
599 for ( ; *suffix
!= '\0'; ++suffix
)
601 include_path
+= (foreignDir
== *suffix
)
607 // Build up the include string from the new path+suffix
608 ACE_CString
include_option ("-I\"", 2 + needToQuote
);
609 include_option
+= include_path
;
613 include_option
+= '"';
616 DRV_cpp_putarg (include_option
.c_str ());
618 idl_global
->add_include_path (include_path
.c_str (),
624 // Adds additional include paths, but after parse_args() has
625 // added user-defined include paths.
627 DRV_cpp_post_init (void)
629 char idl_version_arg
[128];
630 ACE_OS::sprintf (idl_version_arg
, "-D__TAO_IDL_IDL_VERSION=%s",
631 idl_global
->idl_version_
.to_macro ());
632 DRV_cpp_putarg (idl_version_arg
);
634 DRV_cpp_putarg ("-D__TAO_IDL_FEATURES="
635 #ifdef TAO_IDL_FEATURES
638 "\"tao/idl_features.h\""
642 // Add include path for TAO_ROOT/orbsvcs.
643 char* TAO_ROOT
= ACE_OS::getenv ("TAO_ROOT");
645 ACE_CString include_path3
, include_path4
, include_path5
;
647 // When adding new dirs here don't forget to update
648 // FE_Utils::validate_orb_include accordingly.
651 DRV_add_include_path (include_path3
,
658 // If TAO_ROOT isn't defined, assume it's under ACE_ROOT.
659 char* ACE_ROOT
= ACE_OS::getenv ("ACE_ROOT");
663 DRV_add_include_path (include_path3
,
670 #if defined (TAO_IDL_INCLUDE_DIR)
671 DRV_add_include_path (include_path3
,
676 // If ACE_ROOT isn't defined either, there will already
677 // be a warning from DRV_preproc().
678 DRV_add_include_path (include_path3
,
682 #endif /* TAO_IDL_INCLUDE_DIR */
686 // Add include paths for CIAO_ROOT and CIAO_ROOT/ciao.
687 char* CIAO_ROOT
= ACE_OS::getenv ("CIAO_ROOT");
689 // When adding new dirs here don't forget to update
690 // FE_Utils::validate_orb_include accordingly.
693 DRV_add_include_path (include_path4
,
698 DRV_add_include_path (include_path5
,
703 DRV_add_include_path (include_path5
,
709 // Save path of current directory, in case
710 // the call to DRV_sweep_dirs()
711 // below is not a no-op - then the current
712 // working directory will
713 // have to be restored.
714 char cwd_path
[MAXPATHLEN
];
716 if (ACE_OS::getcwd (cwd_path
, sizeof (cwd_path
)) == 0)
718 ACE_ERROR ((LM_ERROR
,
719 "DRV_cpp_post_init: ACE_OS::getcwd failed\n"));
724 // If first arg is non-zero, adds an include path and filename
725 // for every IDL file found in all subdirectories. This is a
726 // no-op for most backends.
727 if (DRV_sweep_dirs (idl_global
->recursion_start (), "") == -1)
729 ACE_ERROR ((LM_ERROR
,
730 "DRV_cpp_post_init: DRV_sweep_dirs (%C) failed\n",
731 idl_global
->recursion_start ()));
736 // This is redundant for most backends, but not if the call to
737 // DRV_sweep_dirs() above is more than a no-op.
738 if (ACE_OS::chdir (cwd_path
) == -1)
740 ACE_ERROR ((LM_ERROR
,
741 "DRV_cpp_post_init: ACE_OS::chdir (%C) failed\n",
748 // Local/internal helper function.
751 // Advances the input char buffer to the first non-white
752 // space character, handles /**/ comments as well.
754 DRV_skip_over_white_spaces (const char *&input
)
758 // Skip the spaces, tabs, vertical-tabs and form feeds.
759 while (' ' == *input
||
767 // Skip any "/*...*/" inline comments
768 // (Note we can't cope with fully multi-line comments since we
769 // are scanning only single lines at a time here.)
772 // This is the first non-white space character (could be
779 // Wasn't the start of a comment so / was the first non-white space character.
783 // Skip over the contents of the comment (if we reach the end of the input
784 // line we have no option but to concider the comment closed, bummer).
787 // Looking for the closing "*/" characters
788 while ('*' != *++input
&& *input
)
791 while ('*' == *input
)
795 } while ('/' != *input
&& *input
);
803 return '\0'; // Reached end of line.
806 // Checks for and skips over #include, positions buffer
807 // at the leading quote character of the filename if
808 // #include is found.
810 DRV_find_include_filename (const char *&input
)
812 // Must have initial # character
813 if ('#' != DRV_skip_over_white_spaces (input
))
818 // Only want #include to match
819 const char *include_str
= "include";
821 if (*include_str
!= DRV_skip_over_white_spaces (++input
))
826 while (*++include_str
== *++input
&& *input
)
829 if (*include_str
|| !*input
)
831 // Not #include (or it ends before filename given).
835 // Next thing is finding the file that has been `#include'd. Skip
836 // over to the starting " or < character.
837 const char start_char
= DRV_skip_over_white_spaces (input
);
838 return ('"' == start_char
|| '<' == start_char
);
841 // We really need to know whether
842 // this line is a "#include ...". If
843 // so, we would like to separate the
844 // "file name" and keep that in the
845 // idl_global. We need them to produce
846 // "#include's in the stubs and
849 DRV_check_for_include (const char *buf
)
851 if (!DRV_find_include_filename (buf
))
856 // Skip over this leading " or < and
857 // copy the filename upto the
858 // closing " or > character.
861 end_char
= ('<' == start_char
) ? '>' : start_char
;
864 incl_file
[MAXPATHLEN
+ 1],
867 while (*buf
!= '\0' && *buf
!= end_char
)
869 // Put Microsoft-style pathnames into a canonical form.
870 if ('\\' == buf
[0] && '\\' == buf
[1])
877 if (fi
== incl_file
+ sizeof (incl_file
) - 1)
879 // Safety valve, filename given was too long!
885 const size_t len
= fi
- incl_file
;
889 return; // Null filename not allowed.
892 ACE_CString
const name_str (incl_file
);
893 ACE_CString
const simple ("orb.idl");
894 ACE_CString
const nix_path ("tao/orb.idl");
895 ACE_CString
const win_path ("tao\\orb.idl");
897 // Some backends pass this file through, others don't.
898 if (name_str
== simple
899 || name_str
== nix_path
900 || name_str
== win_path
)
902 if (idl_global
->pass_orb_idl ())
904 idl_global
->add_to_included_idl_files (incl_file
);
908 DRV_get_orb_idl_includes ();
911 // We have special lookup for orb.idl (TAO_ROOT/tao) that
912 // also kicks in for .pidl files. If one of the latter is
913 // included as a local name only, we add the 'tao/' prefix
914 // so the generated C++ include files will be correct.
915 else if ((5 <= len
&& !ACE_OS::strcmp (incl_file
+ len
- 5, ".pidl"))
916 && !ACE_OS::strchr (incl_file
, '/')
917 && !ACE_OS::strchr (incl_file
, '\\'))
919 ACE_CString
fixed_name ("tao/");
920 fixed_name
+= incl_file
;
922 idl_global
->add_to_included_idl_files (fixed_name
.c_str ());
926 idl_global
->add_to_included_idl_files (incl_file
);
930 // This method turns a line like '#include "a.idl"' into the
931 // line '#include <a.idl>'
933 DRV_convert_includes (char *buf
)
935 const char *input
= buf
;
937 if (!DRV_find_include_filename (input
) || '"' != *input
)
939 return; // Only interested in #include "" type
942 buf
= const_cast<char *> (input
);
944 // Find the closing '"' character.
945 char *open_quote
= buf
;
947 while ('"' != *++buf
&& *buf
!= '\0')
951 // Can't change to #include <> as it
952 // has a > character in the filename!
958 // Replace the quotes with angle brackets.
963 } // End of local/internal namespace
966 DRV_get_orb_idl_includes (void)
968 static char const orb_idl
[] = "tao/orb.idl";
970 // Search for orb.idl in supplied include file search paths.
971 char const * directory
= 0;
972 FILE * fp
= FE_Utils::open_included_file (orb_idl
, directory
);
976 // Fall back on $TAO_ROOT/tao/orb.idl if orb.idl is not in the
978 ACE_CString
orb_idl_path (ACE_CString (idl_global
->tao_root ())
980 + ACE_CString (orb_idl
));
982 fp
= ACE_OS::fopen (orb_idl_path
.c_str (), "r");
986 ACE_ERROR ((LM_ERROR
,
987 "TAO_IDL: cannot open or find file: %C\n",
988 orb_idl_path
.c_str ()));
995 // Make sure the include directory containing orb.idl is passed
996 // to the preprocessor.
997 // This should go after user supplied include paths.
998 ACE_CString include_path_arg
;
999 DRV_add_include_path (include_path_arg
, directory
, "/tao", true);
1002 while (DRV_get_line (fp
))
1004 // Find the included .pidl files in orb.idl and add them to the
1005 // included IDL file list.
1006 DRV_check_for_include (drv_line
);
1009 ACE_OS::fclose (fp
);
1014 DRV_copy_input (FILE *fin
,
1017 const char *orig_filename
)
1021 ACE_ERROR ((LM_ERROR
,
1022 "%C: cannot open temp file \"%C\" for copying from \"%C\": %m\n",
1023 idl_global
->prog_name (),
1032 ACE_ERROR ((LM_ERROR
,
1033 "%C: cannot open input file\n",
1034 idl_global
->prog_name ()));
1039 #if !defined (ACE_WIN32)
1044 // Convert single \ into double \ otherwise MSVC++ pre-processor
1045 // gets awfully confused.
1046 char buf
[2*MAXPATHLEN
];
1049 for (const char *s
= orig_filename
; *s
!= 0; ++s
)
1065 #endif /* ! ACE_WIN32 */
1067 while (DRV_get_line (fin
))
1069 DRV_convert_includes (drv_line
);
1071 // Print the line to the temporary file.
1076 // We really need to know whether this line is a "#include
1077 // ...". If so, we would like to separate the "file name" and
1078 // keep that in the idl_global. We need them to produce
1079 // "#include's in the stubs and skeletons.
1080 DRV_check_for_include (drv_line
);
1083 // Close the temporary file.
1087 // Strip down a name to the last component,
1088 // i.e. everything after the last '/' or '\' character.
1090 DRV_stripped_name (char *fn
)
1100 l
= ACE_OS::strlen (n
);
1101 int slash_found
= 0;
1103 for (n
+= l
- 1; n
>= fn
&& !slash_found
; n
--)
1105 slash_found
= (*n
== '/' || *n
== '\\');
1118 // Pass input through preprocessor.
1120 DRV_pre_proc (const char *myfile
)
1122 // Check to see that the file is a normal file. If we don't and the file is a
1123 // directory, then the copy would be blank and any error message later might
1126 if (ACE_OS::stat (myfile
, &file_stat
) == -1)
1128 ACE_ERROR ((LM_ERROR
,
1129 "%C: ERROR: Unable to open file (stat) \"%C\": %m\n",
1130 idl_global
->prog_name (),
1134 else if ((file_stat
.st_mode
& S_IFREG
) != S_IFREG
)
1136 ACE_ERROR ((LM_ERROR
,
1137 "%C: ERROR: This is not a regular file: \"%C\"\n",
1138 idl_global
->prog_name (),
1143 const char* tmpdir
= idl_global
->temp_dir ();
1144 static const char temp_file_extension
[] = ".cpp";
1146 static char const tao_idlf_template
[] = "tao-idlf_XXXXXX";
1147 static char const tao_idli_template
[] = "tao-idli_XXXXXX";
1150 ACE_OS::strlen (tmpdir
) + sizeof (temp_file_extension
);
1152 // Prevent a buffer overrun.
1153 if (tlen
+ sizeof (tao_idlf_template
) > sizeof (tmp_file
)
1154 || tlen
+ sizeof (tao_idli_template
) > sizeof (tmp_ifile
))
1156 ACE_ERROR ((LM_ERROR
,
1157 "%C: temporary path/filename length is greater than "
1158 "length allowed by platform\n",
1159 idl_global
->prog_name ()));
1164 ACE_OS::strcpy (tmp_file
, tmpdir
);
1165 ACE_OS::strcpy (tmp_ifile
, tmpdir
);
1167 // Append temporary filename template to temporary directory.
1168 ACE_OS::strcat (tmp_file
, tao_idlf_template
);
1169 ACE_OS::strcat (tmp_ifile
, tao_idli_template
);
1171 ACE_HANDLE
const ti_fd
= ACE_OS::mkstemp (tmp_ifile
);
1173 if (ti_fd
== ACE_INVALID_HANDLE
)
1175 ACE_ERROR ((LM_ERROR
,
1176 "%C: Unable to create temporary file \"%C\": %m\n",
1177 idl_global
->prog_name (),
1183 ACE_HANDLE
const tf_fd
= ACE_OS::mkstemp (tmp_file
);
1185 if (tf_fd
== ACE_INVALID_HANDLE
)
1187 ACE_ERROR ((LM_ERROR
,
1188 "%C: Unable to create temporary file \"%C\": %m\n",
1189 idl_global
->prog_name (),
1192 (void) ACE_OS::unlink (tmp_ifile
);
1196 char tmp_cpp_file
[MAXPATHLEN
+ 1] = { 0 };
1197 char tmp_cpp_ifile
[MAXPATHLEN
+ 1] = { 0 };
1199 // Append C++ source file extension. Temporary files will be renamed
1200 // to these filenames.
1201 ACE_OS::strcpy (tmp_cpp_file
, tmp_file
);
1202 ACE_OS::strcpy (tmp_cpp_ifile
, tmp_ifile
);
1203 ACE_OS::strcat (tmp_cpp_file
, temp_file_extension
);
1204 ACE_OS::strcat (tmp_cpp_ifile
, temp_file_extension
);
1206 char * const t_file
= tmp_cpp_file
;
1207 char * const t_ifile
= tmp_cpp_ifile
;
1209 ACE_OS::close (tf_fd
);
1211 // Rename temporary files so that they have extensions accepted
1212 // by the preprocessor.
1213 FILE * const file
= ACE_OS::fopen (myfile
, "r");
1216 ACE_ERROR ((LM_ERROR
,
1217 "%C: ERROR: Unable to open file (fopen) \"%C\": %m\n",
1218 idl_global
->prog_name (),
1220 (void) ACE_OS::unlink (tmp_ifile
);
1221 (void) ACE_OS::unlink (tmp_file
);
1225 DRV_copy_input (file
,
1226 ACE_OS::fdopen (ti_fd
, ACE_TEXT("w")),
1229 ACE_OS::fclose (file
);
1231 UTL_String
*utl_string
= 0;
1233 #if defined (ACE_OPENVMS)
1235 char main_abspath
[MAXPATHLEN
] = "";
1236 char trans_path
[MAXPATHLEN
] = "";
1237 char *main_fullpath
=
1238 ACE_OS::realpath (IDL_GlobalData::translateName (myfile
, trans_path
),
1241 if (main_fullpath
== 0)
1243 ACE_ERROR ((LM_ERROR
,
1244 ACE_TEXT ("Unable to construct full file pathname\n")));
1246 (void) ACE_OS::unlink (tmp_ifile
);
1247 (void) ACE_OS::unlink (tmp_file
);
1251 ACE_NEW (utl_string
,
1252 UTL_String (main_fullpath
, true));
1254 idl_global
->set_main_filename (utl_string
);
1257 ACE_NEW (utl_string
,
1258 UTL_String (myfile
, true));
1260 idl_global
->set_main_filename (utl_string
);
1263 ACE_Auto_String_Free
safety (ACE_OS::strdup (myfile
));
1265 UTL_String
*stripped_tmp
= 0;
1266 ACE_NEW (stripped_tmp
,
1267 UTL_String (DRV_stripped_name (safety
.get ()), true));
1269 idl_global
->set_stripped_filename (stripped_tmp
);
1271 UTL_String
*real_tmp
= 0;
1273 UTL_String (t_ifile
, true));
1275 idl_global
->set_real_filename (real_tmp
);
1277 // We use ACE instead of the (low level) fork facilities, this also
1279 ACE_Process process
;
1281 DRV_cpp_expand_output_arg (t_file
);
1282 DRV_cpp_putarg (t_ifile
);
1283 DRV_cpp_putarg (0); // Null terminate the DRV_arglist.
1285 // For complex builds, the default
1286 // command line buffer size of 1024
1287 // is often not enough. We determine
1288 // the required space and arg nr
1289 // dynamically here.
1290 ACE_Process_Options
cpp_options (1, // Inherit environment.
1291 DRV_cpp_calc_total_argsize (),
1296 if (cpp_options
.command_line (DRV_arglist
) != 0)
1298 ACE_ERROR ((LM_ERROR
,
1299 ACE_TEXT ("%C: command line processing \"%s\" failed\n"),
1300 idl_global
->prog_name (),
1303 (void) ACE_OS::unlink (tmp_ifile
);
1304 (void) ACE_OS::unlink (tmp_file
);
1308 // Rename temporary files so that they have extensions accepted
1309 // by the preprocessor. Renaming is (supposed to be) an atomic
1310 // operation so we shouldn't be susceptible to attack.
1311 if (ACE_OS::rename (tmp_file
, t_file
) != 0)
1313 ACE_ERROR ((LM_ERROR
,
1314 "%C: Unable to rename temporary "
1315 "file \"%C\" to \"%C\": %m\n",
1316 idl_global
->prog_name (),
1321 (void) ACE_OS::unlink (tmp_ifile
);
1322 (void) ACE_OS::unlink (tmp_file
);
1326 if (ACE_OS::rename (tmp_ifile
, t_ifile
) != 0)
1328 ACE_ERROR ((LM_ERROR
,
1329 "%C: Unable to rename temporary "
1330 "file \"%C\" to \"%C\": %m\n",
1331 idl_global
->prog_name (),
1335 (void) ACE_OS::unlink (tmp_ifile
);
1336 (void) ACE_OS::unlink (t_file
);
1340 // Remove any existing output file.
1341 (void) ACE_OS::unlink (t_file
);
1343 ACE_HANDLE fd
= ACE_INVALID_HANDLE
;
1345 if (output_arg_format
== 0)
1347 // If the following open() fails, then we're either being hit with a
1348 // symbolic link attack, or another process opened the file before
1350 #if defined (ACE_OPENVMS)
1351 //FUZZ: disable check_for_lack_ACE_OS
1352 fd
= ::open (t_file
, O_WRONLY
| O_CREAT
| O_EXCL
,
1353 ACE_DEFAULT_FILE_PERMS
,
1354 "shr=get,put,upd", "ctx=rec", "fop=dfw");
1355 //FUZZ: enable check_for_lack_ACE_OS
1357 fd
= ACE_OS::open (t_file
,
1358 O_WRONLY
| O_CREAT
| O_EXCL
,
1359 ACE_DEFAULT_FILE_PERMS
);
1362 if (fd
== ACE_INVALID_HANDLE
)
1364 ACE_ERROR ((LM_ERROR
,
1365 "%C: cannot open temp file"
1366 " \"%C\" for writing: %m\n",
1367 idl_global
->prog_name (),
1370 (void) ACE_OS::unlink (t_file
);
1371 (void) ACE_OS::unlink (t_ifile
);
1375 if (cpp_options
.set_handles (ACE_INVALID_HANDLE
, fd
) == -1)
1377 ACE_ERROR ((LM_ERROR
, "%C: cannot set stdout for child process: %m\n",
1378 idl_global
->prog_name ()));
1384 if (idl_global
->compile_flags () & IDL_CF_INFORMATIVE
)
1386 ACE_DEBUG ((LM_DEBUG
, "%C: spawning: %s\n",
1387 idl_global
->prog_name (),
1388 cpp_options
.command_line_buf ()));
1391 if (process
.spawn (cpp_options
) == ACE_INVALID_PID
)
1393 ACE_ERROR ((LM_ERROR
,
1394 "%C: spawn of \"%s\" failed\n",
1395 idl_global
->prog_name (),
1399 (void) ACE_OS::unlink (t_file
);
1400 (void) ACE_OS::unlink (t_ifile
);
1404 if (fd
!= ACE_INVALID_HANDLE
)
1406 // Close the output file on the parent process.
1407 if (ACE_OS::close (fd
) == -1)
1409 ACE_ERROR ((LM_ERROR
,
1410 "%C: cannot close temp file \"%C\" on parent: %m\n",
1411 idl_global
->prog_name (),
1414 (void) ACE_OS::unlink (t_file
);
1415 (void) ACE_OS::unlink (t_ifile
);
1420 // Remove the null termination and the
1421 // input file from the DRV_arglist,
1422 // the next file will the previous args.
1425 const_cast<ACE_TCHAR
*> (DRV_arglist
[DRV_argcount
]));
1426 DRV_arglist
[DRV_argcount
] = 0;
1427 ACE_exitcode status
= 0;
1429 if (process
.wait (&status
) == ACE_INVALID_PID
)
1431 ACE_ERROR ((LM_ERROR
,
1432 "%C: wait for child process failed\n",
1433 idl_global
->prog_name ()));
1435 (void) ACE_OS::unlink (t_file
);
1436 (void) ACE_OS::unlink (t_ifile
);
1440 if (WIFEXITED ((status
)))
1442 // Child terminated normally?
1443 if (WEXITSTATUS ((status
)) != 0)
1445 errno
= WEXITSTATUS ((status
));
1447 ACE_ERROR ((LM_ERROR
,
1448 "%C: preprocessor \"%s\" "
1449 "returned with an error\n",
1450 idl_global
->prog_name (),
1453 (void) ACE_OS::unlink (t_file
);
1454 (void) ACE_OS::unlink (t_ifile
);
1460 // Child didn't call exit(); perhaps it received a signal?
1463 ACE_ERROR ((LM_ERROR
,
1464 "%C: preprocessor \"%s\" appears "
1465 "to have been interrupted\n",
1466 idl_global
->prog_name (),
1469 (void) ACE_OS::unlink (t_file
);
1470 (void) ACE_OS::unlink (t_ifile
);
1473 // TODO: Manage problems in the
1474 // pre-processor, in the previous
1475 // version the current process
1476 // would exit if the pre-processor
1477 // returned with error.
1479 #if defined (ACE_OPENVMS)
1480 cpp_options
.release_handles();
1483 FILE * const yyin
= ACE_OS::fopen (t_file
, "r");
1487 ACE_ERROR ((LM_ERROR
,
1488 "%C: Could not open cpp "
1489 "output file \"%C\": %m\n",
1490 idl_global
->prog_name (),
1493 (void) ACE_OS::unlink (t_file
);
1494 (void) ACE_OS::unlink (t_ifile
);
1500 if (idl_global
->compile_flags () & IDL_CF_ONLY_PREPROC
)
1502 FILE *preproc
= ACE_OS::fopen (t_file
, "r");
1503 char buffer
[ACE_MAXLOGMSGLEN
];
1508 ACE_ERROR ((LM_ERROR
,
1509 "%C: Could not open cpp "
1510 "output file \"%C\": %m\n",
1511 idl_global
->prog_name (),
1514 (void) ACE_OS::unlink (t_file
);
1515 (void) ACE_OS::unlink (t_ifile
);
1519 // ACE_DEBUG sends to stderr - we want stdout for this dump
1520 // of the preprocessor output. So we modify the singleton that
1521 // was created in this process. Since IDL_CF_ONLY_PREPROC causes
1522 // an (almost) immediate exit below, we don't have to restore
1523 // the singleton's default parameters.
1524 ACE_Log_Msg
*out
= ACE_Log_Msg::instance ();
1525 out
->msg_ostream (&cout
);
1526 out
->clr_flags (ACE_Log_Msg::STDERR
);
1527 out
->set_flags (ACE_Log_Msg::OSTREAM
);
1529 while ((bytes
= ACE_OS::fread (buffer
,
1531 ACE_MAXLOGMSGLEN
- 1,
1536 ACE_DEBUG ((LM_DEBUG
, buffer
));
1539 ACE_OS::fclose (preproc
);
1542 if (ACE_OS::unlink (t_ifile
) == -1)
1544 ACE_ERROR ((LM_ERROR
,
1545 "%C: Could not remove cpp "
1546 "input file \"%C\": %m\n",
1547 idl_global
->prog_name (),
1553 if (ACE_OS::unlink (t_file
) == -1)
1555 ACE_ERROR ((LM_ERROR
,
1556 "%C: Could not remove cpp "
1557 "output file \"%C\": %m\n",
1558 idl_global
->prog_name (),