Panda3D
|
00001 // Filename: withOutputFile.cxx 00002 // Created by: drose (11Apr01) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "withOutputFile.h" 00016 #include "executionEnvironment.h" 00017 #include "zStream.h" 00018 00019 #include "pnotify.h" 00020 00021 //////////////////////////////////////////////////////////////////// 00022 // Function: WithOutputFile::Constructor 00023 // Access: Public 00024 // Description: 00025 //////////////////////////////////////////////////////////////////// 00026 WithOutputFile:: 00027 WithOutputFile(bool allow_last_param, bool allow_stdout, 00028 bool binary_output) { 00029 _allow_last_param = allow_last_param; 00030 _allow_stdout = allow_stdout; 00031 _binary_output = binary_output; 00032 _got_output_filename = false; 00033 _output_ptr = (ostream *)NULL; 00034 _owns_output_ptr = false; 00035 } 00036 00037 //////////////////////////////////////////////////////////////////// 00038 // Function: WithOutputFile::Destructor 00039 // Access: Public, Virtual 00040 // Description: 00041 //////////////////////////////////////////////////////////////////// 00042 WithOutputFile:: 00043 ~WithOutputFile() { 00044 if (_owns_output_ptr) { 00045 delete _output_ptr; 00046 _owns_output_ptr = false; 00047 } 00048 } 00049 00050 //////////////////////////////////////////////////////////////////// 00051 // Function: WithOutputFile::get_output 00052 // Access: Public 00053 // Description: Returns an output stream that corresponds to the 00054 // user's intended egg file output--either stdout, or 00055 // the named output file. 00056 //////////////////////////////////////////////////////////////////// 00057 ostream &WithOutputFile:: 00058 get_output() { 00059 if (_output_ptr == (ostream *)NULL) { 00060 if (!_got_output_filename) { 00061 // No filename given; use standard output. 00062 if (!_allow_stdout) { 00063 nout << "No output filename specified.\n"; 00064 exit(1); 00065 } 00066 _output_ptr = &cout; 00067 _owns_output_ptr = false; 00068 00069 } else { 00070 // Attempt to open the named file. 00071 unlink(_output_filename.c_str()); 00072 _output_filename.make_dir(); 00073 00074 bool pz_file = false; 00075 #ifdef HAVE_ZLIB 00076 if (_output_filename.get_extension() == "pz") { 00077 // The filename ends in .pz, which means to automatically compress 00078 // the file that we write. 00079 pz_file = true; 00080 } 00081 #endif // HAVE_ZLIB 00082 00083 if (_binary_output || pz_file) { 00084 _output_filename.set_binary(); 00085 } else { 00086 _output_filename.set_text(); 00087 } 00088 00089 _output_stream.clear(); 00090 if (!_output_filename.open_write(_output_stream)) { 00091 nout << "Unable to write to " << _output_filename << "\n"; 00092 exit(1); 00093 } 00094 nout << "Writing " << _output_filename << "\n"; 00095 _output_ptr = &_output_stream; 00096 _owns_output_ptr = false; 00097 00098 #ifdef HAVE_ZLIB 00099 if (pz_file) { 00100 _output_ptr = new OCompressStream(_output_ptr, _owns_output_ptr); 00101 _owns_output_ptr = true; 00102 } 00103 #endif // HAVE_ZLIB 00104 } 00105 } 00106 return *_output_ptr; 00107 } 00108 00109 //////////////////////////////////////////////////////////////////// 00110 // Function: WithOutputFile::close_output 00111 // Access: Public 00112 // Description: Closes the output stream previously opened by 00113 // get_output(). A subsequent call to get_output() will 00114 // open a new stream. 00115 //////////////////////////////////////////////////////////////////// 00116 void WithOutputFile:: 00117 close_output() { 00118 if (_owns_output_ptr) { 00119 delete _output_ptr; 00120 _owns_output_ptr = false; 00121 } 00122 _output_ptr = NULL; 00123 _output_stream.close(); 00124 } 00125 00126 00127 00128 //////////////////////////////////////////////////////////////////// 00129 // Function: WithOutputFile::has_output_filename 00130 // Access: Public 00131 // Description: Returns true if the user specified an output 00132 // filename, false otherwise (e.g. the output file is 00133 // implicitly stdout). 00134 //////////////////////////////////////////////////////////////////// 00135 bool WithOutputFile:: 00136 has_output_filename() const { 00137 return _got_output_filename; 00138 } 00139 00140 //////////////////////////////////////////////////////////////////// 00141 // Function: WithOutputFile::get_output_filename 00142 // Access: Public 00143 // Description: If has_output_filename() returns true, this is the 00144 // filename that the user specified. Otherwise, it 00145 // returns the empty string. 00146 //////////////////////////////////////////////////////////////////// 00147 Filename WithOutputFile:: 00148 get_output_filename() const { 00149 if (_got_output_filename) { 00150 return _output_filename; 00151 } 00152 return Filename(); 00153 } 00154 00155 //////////////////////////////////////////////////////////////////// 00156 // Function: WithOutputFile::check_last_arg 00157 // Access: Protected 00158 // Description: Checks if the last filename on the argument list is 00159 // a file with the expected extension (if 00160 // _allow_last_param was set true), and removes it from 00161 // the argument list if it is. Returns true if the 00162 // arguments are good, false if something is invalid. 00163 // 00164 // minimum_args is the number of arguments we know must 00165 // be input parameters and therefore cannot be 00166 // interpreted as output filenames. 00167 //////////////////////////////////////////////////////////////////// 00168 bool WithOutputFile:: 00169 check_last_arg(ProgramBase::Args &args, int minimum_args) { 00170 if (_allow_last_param && !_got_output_filename && 00171 (int)args.size() > minimum_args) { 00172 Filename filename = Filename::from_os_specific(args.back()); 00173 00174 if (!_preferred_extension.empty() && 00175 ("." + filename.get_extension()) != _preferred_extension) { 00176 // This argument must not be an output filename. 00177 if (!_allow_stdout) { 00178 nout << "Output filename " << filename 00179 << " does not end in " << _preferred_extension 00180 << ". If this is really what you intended, " 00181 "use the -o output_file syntax.\n"; 00182 return false; 00183 } 00184 00185 } else { 00186 // This argument appears to be an output filename. 00187 _got_output_filename = true; 00188 _output_filename = filename; 00189 args.pop_back(); 00190 00191 if (!verify_output_file_safe()) { 00192 return false; 00193 } 00194 } 00195 } 00196 00197 return true; 00198 } 00199 00200 //////////////////////////////////////////////////////////////////// 00201 // Function: WithOutputFile::verify_output_file_safe 00202 // Access: Protected 00203 // Description: This is called when the output file is given as the 00204 // last parameter on the command line. Since this is a 00205 // fairly dangerous way to specify the output file (it's 00206 // easy to accidentally overwrite an input file this 00207 // way), the convention is to disallow this syntax if 00208 // the output file already exists. 00209 // 00210 // This function will test if the output file exists, 00211 // and issue a warning message if it does, returning 00212 // false. If all is well, it will return true. 00213 //////////////////////////////////////////////////////////////////// 00214 bool WithOutputFile:: 00215 verify_output_file_safe() const { 00216 nassertr(_got_output_filename, false); 00217 00218 if (_output_filename.exists()) { 00219 nout << "The output filename " << _output_filename << " already exists. " 00220 "If you wish to overwrite it, you must use the -o option to specify " 00221 "the output filename, instead of simply specifying it as the last " 00222 "parameter.\n"; 00223 return false; 00224 } 00225 return true; 00226 }