add -noabs to many egg tools

This commit is contained in:
David Rose 2004-11-29 22:53:11 +00:00
parent 1cc8cf5aa1
commit b4280f10cf
28 changed files with 378 additions and 57 deletions

View File

@ -17,6 +17,30 @@
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: SomethingToEggConverter::clear_error
// Access: Public
// Description: Resets the error flag to the no-error state.
// had_error() will return false until a new error is
// generated.
////////////////////////////////////////////////////////////////////
INLINE void SomethingToEggConverter::
clear_error() {
_error = false;
}
////////////////////////////////////////////////////////////////////
// Function: SomethingToEggConverter::had_error
// Access: Public
// Description: Returns true if an error was detected during the
// conversion process (unless _allow_errors is true),
// false otherwise.
////////////////////////////////////////////////////////////////////
INLINE bool SomethingToEggConverter::
had_error() const {
return !_allow_errors && (_error || _path_replace->had_error());
}
////////////////////////////////////////////////////////////////////
// Function: SomethingToEggConverter::set_path_replace
// Access: Public

View File

@ -144,9 +144,7 @@ handle_external_reference(EggGroupNode *egg_parent,
if (!ext->convert_file(ref_filename)) {
delete ext;
nout << "Unable to read external reference: " << ref_filename << "\n";
if (!_allow_errors) {
_error = true;
}
return false;
}

View File

@ -49,6 +49,9 @@ public:
virtual SomethingToEggConverter *make_copy()=0;
INLINE void clear_error();
INLINE bool had_error() const;
INLINE void set_path_replace(PathReplace *path_replace);
INLINE PathReplace *get_path_replace();
INLINE const PathReplace *get_path_replace() const;

View File

@ -91,14 +91,14 @@ get_extension() const {
////////////////////////////////////////////////////////////////////
bool DXFToEggConverter::
convert_file(const Filename &filename) {
_error = false;
clear_error();
if (_egg_data->get_coordinate_system() == CS_default) {
_egg_data->set_coordinate_system(CS_zup_right);
}
process(filename);
return !_error;
return !had_error();
}
////////////////////////////////////////////////////////////////////

View File

@ -657,6 +657,8 @@ run() {
}
}
pal->set_noabs(_noabs);
if (_report_pi) {
pal->report_pi();
exit(0);
@ -724,6 +726,8 @@ run() {
}
// And process the egg files named for addition.
bool all_eggs_valid = true;
string egg_comment = get_exec_command();
Eggs::const_iterator ei;
for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) {
@ -733,11 +737,19 @@ run() {
string name = source_filename.get_basename();
EggFile *egg_file = pal->get_egg_file(name);
egg_file->from_command_line(egg_data, source_filename, dest_filename,
egg_comment);
if (!egg_file->from_command_line(egg_data, source_filename, dest_filename,
egg_comment)) {
all_eggs_valid = false;
} else {
pal->add_command_line_egg(egg_file);
}
}
if (!all_eggs_valid) {
nout << "Errors reading egg file(s).\n";
exit(1);
}
if (_optimal) {
// If we're asking for an optimal packing, throw away the old
@ -767,11 +779,13 @@ run() {
}
}
if (okflag) {
pal->generate_images(_redo_all);
if (!pal->write_eggs()) {
okflag = false;
}
}
if (!_nodb) {
// Make up a temporary filename to write the state file to, then

View File

@ -39,13 +39,16 @@ EggBase() {
&EggBase::dispatch_coordinate_system,
&_got_coordinate_system, &_coordinate_system);
_coordinate_system = CS_yup_right;
_normals_mode = NM_preserve;
_normals_threshold = 0.0;
_got_transform = false;
_transform = LMatrix4d::ident_mat();
_got_coordinate_system = false;
_coordinate_system = CS_yup_right;
_noabs = false;
}
////////////////////////////////////////////////////////////////////

View File

@ -72,6 +72,8 @@ protected:
bool _got_coordinate_system;
CoordinateSystem _coordinate_system;
bool _noabs;
};
#endif

View File

@ -35,6 +35,14 @@ EggMultiBase() {
"Force complete loading: load up the egg file along with all of its "
"external references.",
&EggMultiBase::dispatch_none, &_force_complete);
add_option
("noabs", "", 0,
"Don't allow any of the named egg files to have absolute pathnames. "
"If any do, abort with an error. This option is designed to help "
"detect errors when populating or building a standalone model tree, "
"which should be self-contained and include only relative pathnames.",
&EggReader::dispatch_none, &_noabs);
}
////////////////////////////////////////////////////////////////////
@ -124,6 +132,12 @@ read_egg(const Filename &filename) {
return (EggData *)NULL;
}
if (_noabs && data->original_had_absolute_pathnames()) {
nout << filename.get_basename()
<< " includes absolute pathnames!\n";
return (EggData *)NULL;
}
DSearchPath file_path;
file_path.append_directory(filename.get_dirname());

View File

@ -49,6 +49,14 @@ EggReader() {
"external references.",
&EggReader::dispatch_none, &_force_complete);
add_option
("noabs", "", 0,
"Don't allow the input egg file to have absolute pathnames. "
"If it does, abort with an error. This option is designed to help "
"detect errors when populating or building a standalone model tree, "
"which should be self-contained and include only relative pathnames.",
&EggReader::dispatch_none, &_noabs);
_tex_type = (PNMFileType *)NULL;
_delod = -1.0;
}
@ -174,6 +182,12 @@ handle_args(ProgramBase::Args &args) {
exit(1);
}
if (_noabs && file_data.original_had_absolute_pathnames()) {
nout << filename.get_basename()
<< " includes absolute pathnames!\n";
exit(1);
}
DSearchPath file_path;
file_path.append_directory(filename.get_dirname());

View File

@ -52,6 +52,14 @@ SomethingToEgg(const string &format_name,
"Specify the coordinate system of the input " + _format_name +
" file. Normally, this can inferred from the file itself.");
add_option
("noabs", "", 0,
"Don't allow the input " + _format_name + " file to have absolute pathnames. "
"If it does, abort with an error. This option is designed to help "
"detect errors when populating or building a standalone model tree, "
"which should be self-contained and include only relative pathnames.",
&SomethingToEgg::dispatch_none, &_noabs);
add_option
("ignore", "", 0,
"Ignore non-fatal errors and generate an egg file anyway.",
@ -200,6 +208,8 @@ apply_units_scale(EggData &data) {
////////////////////////////////////////////////////////////////////
void SomethingToEgg::
apply_parameters(SomethingToEggConverter &converter) {
_path_replace->_noabs = _noabs;
_path_replace->_exists = true;
converter.set_path_replace(_path_replace);
converter.set_animation_convert(_animation_convert);

View File

@ -163,7 +163,7 @@ convert_flt(const FltHeader *flt_header) {
_egg_data->set_coordinate_system(CS_zup_right);
}
_error = false;
clear_error();
_flt_header = flt_header;
// Generate a default vertex pool.
@ -188,7 +188,7 @@ convert_flt(const FltHeader *flt_header) {
cleanup();
return !_error;
return !had_error();
}
////////////////////////////////////////////////////////////////////
@ -681,9 +681,7 @@ parse_comment(const string &comment, const string &name,
if (p >= comment.length() || comment[p] != '{') {
nout << "No opening brace in comment for "
<< name << "\n\n";
if (!_allow_errors) {
_error = true;
}
return false;
}
@ -697,9 +695,7 @@ parse_comment(const string &comment, const string &name,
if (q == p) {
nout << "No closing brace in comment for "
<< name << "\n\n";
if (!_allow_errors) {
_error = true;
}
return false;
}
@ -708,9 +704,7 @@ parse_comment(const string &comment, const string &name,
if (!egg_node->parse_egg(egg_syntax)) {
nout << "Syntax error in comment for "
<< name << "\n\n";
if (!_allow_errors) {
_error = true;
}
return false;
}

View File

@ -68,6 +68,17 @@ FltToEgg() :
////////////////////////////////////////////////////////////////////
void FltToEgg::
run() {
_data.set_coordinate_system(_coordinate_system);
FltToEggConverter converter;
converter.set_merge_externals(_merge_externals);
converter.set_egg_data(&_data, false);
converter._compose_transforms = _compose_transforms;
converter._allow_errors = _allow_errors;
apply_parameters(converter);
PT(FltHeader) header = new FltHeader(_path_replace);
nout << "Reading " << _input_filename << "\n";
@ -79,15 +90,6 @@ run() {
header->check_version();
_data.set_coordinate_system(_coordinate_system);
FltToEggConverter converter;
converter.set_merge_externals(_merge_externals);
converter.set_egg_data(&_data, false);
converter._compose_transforms = _compose_transforms;
converter._allow_errors = _allow_errors;
apply_parameters(converter);
if (!converter.convert_flt(header)) {
nout << "Errors in conversion.\n";

View File

@ -167,7 +167,7 @@ convert_lwo(const LwoHeader *lwo_header) {
_egg_data->remove_unused_vertices();
cleanup();
return !_error;
return !had_error();
}
////////////////////////////////////////////////////////////////////

View File

@ -272,6 +272,7 @@ get_input_units() {
bool MayaToEggConverter::
convert_maya() {
clear();
clear_error();
if (!open_api()) {
mayaegg_cat.error()
@ -391,6 +392,10 @@ convert_maya() {
reparent_decals(&get_egg_data());
}
if (had_error()) {
all_ok = false;
}
if (all_ok) {
mayaegg_cat.info()
<< "Converted, no errors.\n";

View File

@ -99,6 +99,12 @@ MayaToEgg() :
"Increase verbosity. More v's means more verbose.",
&MayaToEgg::dispatch_count, NULL, &_verbose);
// Unfortunately, the Maya API doesn't allow us to differentiate
// between relative and absolute pathnames--everything comes out as
// an absolute pathname, even if it is stored in the Maya file as a
// relative path. So we can't support -noabs.
remove_option("noabs");
_verbose = 0;
_polygon_tolerance = 0.01;
_transform_type = MayaToEggConverter::TT_model;
@ -159,7 +165,6 @@ run() {
_data.set_coordinate_system(_coordinate_system);
converter.set_egg_data(&_data, false);
apply_parameters(converter);
if (!converter.convert_file(_input_filename)) {
nout << "Errors in conversion.\n";

View File

@ -60,9 +60,10 @@ EggFile() {
// Function: EggFile::from_command_line
// Access: Public
// Description: Accepts the information about the egg file as
// supplied from the command line.
// supplied from the command line. Returns true if the
// egg file is valid, false otherwise.
////////////////////////////////////////////////////////////////////
void EggFile::
bool EggFile::
from_command_line(EggData *data,
const Filename &source_filename,
const Filename &dest_filename,
@ -90,8 +91,21 @@ from_command_line(EggData *data,
// file inherits the default group that was in effect when it was
// specified on the command line.
_default_group = pal->get_default_group();
return true;
}
////////////////////////////////////////////////////////////////////
// Function: EggFile::get_source_filename
// Access: Public
// Description: Returns the filename this egg file was read from.
////////////////////////////////////////////////////////////////////
const Filename &EggFile::
get_source_filename() const {
return _source_filename;
}
////////////////////////////////////////////////////////////////////
// Function: EggFile::scan_textures
// Access: Public
@ -536,7 +550,7 @@ remove_egg() {
// file.
////////////////////////////////////////////////////////////////////
bool EggFile::
read_egg() {
read_egg(bool noabs) {
nassertr(_data == (EggData *)NULL, false);
nassertr(!_source_filename.empty(), false);
@ -554,10 +568,15 @@ read_egg() {
return false;
}
if (noabs && data->original_had_absolute_pathnames()) {
nout << _source_filename.get_basename()
<< " references textures using absolute pathnames!\n";
return false;
}
// Extract the set of textures referenced by this egg file.
EggTextureCollection tc;
tc.find_used_textures(_data);
tc.find_used_textures(data);
// Make sure each tref name is unique within a given file.
tc.uniquify_trefs();
@ -850,7 +869,7 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) {
////////////////////////////////////////////////////////////////////
TypedWritable* EggFile::
make_EggFile(const FactoryParams &params) {
EggFile *me = new EggFile;
EggFile *me = new EggFile();
DatagramIterator scan;
BamReader *manager;

View File

@ -44,11 +44,13 @@ class EggFile : public TypedWritable, public Namable {
public:
EggFile();
void from_command_line(EggData *data,
bool from_command_line(EggData *data,
const Filename &source_filename,
const Filename &dest_filename,
const string &egg_comment);
const Filename &get_source_filename() const;
void scan_textures();
void get_textures(pset<TextureImage *> &result) const;
@ -74,7 +76,7 @@ public:
void update_egg();
void remove_egg();
bool read_egg();
bool read_egg(bool noabs);
void release_egg_data();
bool write_egg();
@ -95,6 +97,7 @@ private:
typedef pvector<TextureReference *> Textures;
Textures _textures;
bool _noabs;
bool _first_txa_match;
PaletteGroups _explicitly_assigned_groups;
PaletteGroup *_default_group;

View File

@ -738,12 +738,12 @@ get_image() {
if (!_new_image) {
if (pal->_shadow_color_type != (PNMFileType *)NULL) {
if (_shadow_image.read(_image)) {
if (_shadow_image.get_filename().exists() && _shadow_image.read(_image)) {
_got_image = true;
return;
}
} else {
if (read(_image)) {
if (get_filename().exists() && read(_image)) {
_got_image = true;
return;
}

View File

@ -102,6 +102,7 @@ public:
Palettizer::
Palettizer() {
_is_valid = true;
_noabs = false;
_generated_image_pattern = "%g_palette_%p_%i";
_map_dirname = "%g";
@ -125,6 +126,36 @@ Palettizer() {
_remap_char_uv = RU_poly;
}
////////////////////////////////////////////////////////////////////
// Function: Palettizer::get_noabs
// Access: Public
// Description: Returns the current setting of the noabs flag. See
// set_noabs().
////////////////////////////////////////////////////////////////////
bool Palettizer::
get_noabs() const {
return _noabs;
}
////////////////////////////////////////////////////////////////////
// Function: Palettizer::set_noabs
// Access: Public
// Description: Changes the current setting of the noabs flag.
//
// If this flag is true, then it is an error to process
// an egg file that contains absolute pathname
// references. This flag is intended to help detect egg
// files that are incorrectly built within a model tree
// (which should use entirely relative pathnames).
//
// This flag must be set before any egg files are
// processed.
////////////////////////////////////////////////////////////////////
void Palettizer::
set_noabs(bool noabs) {
_noabs = noabs;
}
////////////////////////////////////////////////////////////////////
// Function: Palettizer::is_valid
// Access: Public
@ -660,7 +691,7 @@ read_stale_eggs(bool redo_all) {
EggFile *egg_file = (*ei).second;
if (!egg_file->has_data() &&
(egg_file->is_stale() || redo_all)) {
if (!egg_file->read_egg()) {
if (!egg_file->read_egg(_noabs)) {
invalid_eggs.push_back(ei);
} else {
@ -676,10 +707,29 @@ read_stale_eggs(bool redo_all) {
for (ii = invalid_eggs.begin(); ii != invalid_eggs.end(); ++ii) {
EggFiles::iterator ei = (*ii);
EggFile *egg_file = (*ei).second;
nout << "Removing " << (*ei).first << "\n";
if (egg_file->get_source_filename().exists()) {
// If there is an invalid egg file, remove it; hopefully it will
// get rebuilt properly next time.
nout << "Removing invalid egg file: "
<< FilenameUnifier::make_user_filename(egg_file->get_source_filename())
<< "\n";
egg_file->get_source_filename().unlink();
okflag = false;
} else {
// If the egg file is simply missing, quietly remove any record
// of it from the database.
egg_file->remove_egg();
_egg_files.erase(ei);
}
}
if (!okflag) {
nout << "\n"
<< "Some errors in egg files encountered.\n"
<< "Re-run make install or make opt-pal to try to regenerate these.\n\n";
}
return okflag;
}
@ -701,7 +751,7 @@ write_eggs() {
if (egg_file->had_data()) {
if (!egg_file->has_data()) {
// Re-read the egg file.
bool read_ok = egg_file->read_egg();
bool read_ok = egg_file->read_egg(_noabs);
if (!read_ok) {
nout << "Error! Unable to re-read egg file.\n";
okflag = false;

View File

@ -48,6 +48,9 @@ class Palettizer : public TypedWritable {
public:
Palettizer();
bool get_noabs() const;
void set_noabs(bool noabs);
bool is_valid() const;
void report_pi() const;
void report_statistics() const;
@ -91,15 +94,16 @@ public:
bool _is_valid;
// These values are not stored in the bam file, but are specific to
// each session.
// These values are not stored in the textures.boo file, but are
// specific to each session.
TxaFile _txa_file;
string _default_groupname;
string _default_groupdir;
bool _noabs;
// The following parameter values specifically relate to textures
// and palettes. These values are stored in the bam file for future
// reference.
// and palettes. These values are stored in the textures.boo file
// for future reference.
string _generated_image_pattern;
string _map_dirname;
Filename _shadow_dirname;

View File

@ -6,6 +6,7 @@
#define SOURCES \
animationConvert.cxx animationConvert.h \
config_pandatoolbase.cxx config_pandatoolbase.h \
distanceUnit.cxx distanceUnit.h \
pandatoolbase.cxx pandatoolbase.h pandatoolsymbols.h \
pathReplace.cxx pathReplace.I pathReplace.h \
@ -13,6 +14,7 @@
#define INSTALL_HEADERS \
animationConvert.h \
config_pandatoolbase.h \
distanceUnit.h \
pandatoolbase.h pandatoolsymbols.h \
pathReplace.I pathReplace.h \

View File

@ -0,0 +1,39 @@
// Filename: config_pandatoolbase.cxx
// Created by: drose (29Nov04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "config_pandatoolbase.h"
NotifyCategoryDef(pandatoolbase, "");
////////////////////////////////////////////////////////////////////
// Function: init_libpandatoolbase
// Description: Initializes the library. This must be called at
// least once before any of the functions or classes in
// this library can be used. Normally it will be
// called by the static initializers and need not be
// called explicitly, but special cases exist.
////////////////////////////////////////////////////////////////////
void
init_libpandatoolbase() {
static bool initialized = false;
if (initialized) {
return;
}
initialized = true;
}

View File

@ -0,0 +1,30 @@
// Filename: config_pandatoolbase.h
// Created by: drose (29Nov04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef CONFIG_PANDATOOLBASE_H
#define CONFIG_PANDATOOLBASE_H
#include "pandatoolbase.h"
#include "notifyCategoryProxy.h"
NotifyCategoryDeclNoExport(pandatoolbase);
extern void init_libpandatoolbase();
#endif

View File

@ -17,6 +17,29 @@
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: PathReplace::clear_error
// Access: Public
// Description: Resets the error flag to the no-error state.
// had_error() will return false until a new error is
// generated.
////////////////////////////////////////////////////////////////////
INLINE void PathReplace::
clear_error() {
_error_flag = false;
}
////////////////////////////////////////////////////////////////////
// Function: PathReplace::had_error
// Access: Public
// Description: Returns true if an error was detected since the last
// call to clear_error(), false otherwise.
////////////////////////////////////////////////////////////////////
INLINE bool PathReplace::
had_error() const {
return _error_flag;
}
////////////////////////////////////////////////////////////////////
// Function: PathReplace::clear
// Access: Public
@ -24,6 +47,7 @@
////////////////////////////////////////////////////////////////////
INLINE void PathReplace::
clear() {
clear_error();
_entries.clear();
}

View File

@ -18,6 +18,7 @@
#include "pathReplace.h"
#include "config_util.h"
#include "config_pandatoolbase.h"
#include "indent.h"
////////////////////////////////////////////////////////////////////
@ -28,6 +29,9 @@
PathReplace::
PathReplace() {
_path_store = PS_keep;
_noabs = false;
_exists = false;
_error_flag = false;
}
////////////////////////////////////////////////////////////////////
@ -96,9 +100,31 @@ match_path(const Filename &orig_filename,
// The file couldn't be found anywhere. Did we at least get any
// prefix match?
if (got_match) {
if (_exists) {
_error_flag = true;
pandatoolbase_cat.error()
<< "File does not exist: " << match << "\n";
} else if (pandatoolbase_cat.is_debug()) {
pandatoolbase_cat.debug()
<< "File does not exist: " << match << "\n";
}
return match;
}
if (!orig_filename.is_local()) {
// Ok, we didn't match any specified prefixes. If the file is an
// absolute pathname and we have _noabs set, that's an error.
if (_noabs) {
_error_flag = true;
pandatoolbase_cat.error()
<< "Absolute pathname: " << orig_filename << "\n";
} else if (pandatoolbase_cat.is_debug()) {
pandatoolbase_cat.debug()
<< "Absolute pathname: " << orig_filename << "\n";
}
}
// Well, we still haven't found it; look it up on the search path as
// is.
if (_path_store != PS_keep) {
@ -111,7 +137,16 @@ match_path(const Filename &orig_filename,
}
}
// Nope, couldn't find anything. Just return the original filename.
// Nope, couldn't find anything. This is an error, but just return
// the original filename.
if (_exists) {
_error_flag = true;
pandatoolbase_cat.error()
<< "File does not exist: " << orig_filename << "\n";
} else if (pandatoolbase_cat.is_debug()) {
pandatoolbase_cat.debug()
<< "File does not exist: " << orig_filename << "\n";
}
return orig_filename;
}
@ -125,6 +160,10 @@ match_path(const Filename &orig_filename,
////////////////////////////////////////////////////////////////////
Filename PathReplace::
store_path(const Filename &orig_filename) {
if (orig_filename.empty()) {
return orig_filename;
}
if (_path_directory.is_local()) {
_path_directory.make_absolute();
}
@ -190,6 +229,11 @@ write(ostream &out, int indent_level) const {
default:
break;
}
if (_noabs) {
indent(out, indent_level)
<< "-noabs\n";
}
}
////////////////////////////////////////////////////////////////////

View File

@ -45,6 +45,9 @@ public:
PathReplace();
~PathReplace();
INLINE void clear_error();
INLINE bool had_error() const;
INLINE void clear();
INLINE void add_pattern(const string &orig_prefix, const string &replacement_prefix);
@ -71,6 +74,16 @@ public:
PathStore _path_store;
Filename _path_directory;
// If this is this true, then the error flag is set (see had_error()
// and clear_error()) if any Filename passed to match_path() or
// convert_path(), and unmatched by one of the prefixes, happens to
// be an absolute pathname.
bool _noabs;
// If this is true, then the error flag is set if any Filename
// passed to match_path() or convert_path() cannot be found.
bool _exists;
private:
class Component {
public:
@ -100,6 +113,8 @@ private:
typedef pvector<Entry> Entries;
Entries _entries;
bool _error_flag;
};
#include "pathReplace.I"

View File

@ -98,6 +98,8 @@ get_extension() const {
////////////////////////////////////////////////////////////////////
bool VRMLToEggConverter::
convert_file(const Filename &filename) {
clear_error();
VrmlScene *scene = parse_vrml(filename);
if (scene == (VrmlScene *)NULL) {
return false;
@ -122,7 +124,7 @@ convert_file(const Filename &filename) {
vrml_node((*csi)._node, &get_egg_data(), LMatrix4d::ident_mat());
}
return true;
return !had_error();
}
////////////////////////////////////////////////////////////////////

View File

@ -116,6 +116,7 @@ get_extension() const {
bool XFileToEggConverter::
convert_file(const Filename &filename) {
close();
clear_error();
if (!_x_file->read(filename)) {
nout << "Unable to open X file: " << filename << "\n";
@ -148,7 +149,7 @@ convert_file(const Filename &filename) {
return false;
}
return true;
return !had_error();
}
////////////////////////////////////////////////////////////////////