Changeset 2724b4e
- Timestamp:
- Sep 16, 2020, 1:48:17 PM (3 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 673eb7a
- Parents:
- c402739 (diff), da9a27c (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Files:
-
- 9 added
- 24 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/Makefile.am
rc402739 r2724b4e 62 62 iterator.hfa \ 63 63 limits.hfa \ 64 memory.hfa \ 64 65 parseargs.hfa \ 65 66 rational.hfa \ -
libcfa/src/concurrency/monitor.cfa
rc402739 r2724b4e 89 89 __cfaabi_dbg_print_safe( "Kernel : %10p Entering mon %p (%p)\n", thrd, this, this->owner); 90 90 91 if( !this->owner ) { 91 if( unlikely(0 != (0x1 & (uintptr_t)this->owner)) ) { 92 abort( "Attempt by thread \"%.256s\" (%p) to access joined monitor %p.", thrd->self_cor.name, thrd, this ); 93 } 94 else if( !this->owner ) { 92 95 // No one has the monitor, just take it 93 96 __set_owner( this, thrd ); … … 137 140 } 138 141 139 static void __dtor_enter( $monitor * this, fptr_t func ) {142 static void __dtor_enter( $monitor * this, fptr_t func, bool join ) { 140 143 // Lock the monitor spinlock 141 144 lock( this->lock __cfaabi_dbg_ctx2 ); … … 157 160 return; 158 161 } 159 else if( this->owner == thrd ) {162 else if( this->owner == thrd && !join) { 160 163 // We already have the monitor... but where about to destroy it so the nesting will fail 161 164 // Abort! 162 165 abort( "Attempt to destroy monitor %p by thread \"%.256s\" (%p) in nested mutex.", this, thrd->self_cor.name, thrd ); 166 } 167 // SKULLDUGGERY: join will act as a dtor so it would normally trigger to above check 168 // to avoid that it sets the owner to the special value thrd | 1p before exiting 169 else if( this->owner == ($thread*)(1 | (uintptr_t)thrd) ) { 170 // restore the owner and just return 171 __cfaabi_dbg_print_safe( "Kernel : Destroying free mon %p\n", this); 172 173 // No one has the monitor, just take it 174 this->owner = thrd; 175 176 verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this ); 177 178 unlock( this->lock ); 179 return; 163 180 } 164 181 … … 251 268 252 269 // Leave single monitor for the last time 253 void __dtor_leave( $monitor * this ) {270 void __dtor_leave( $monitor * this, bool join ) { 254 271 __cfaabi_dbg_debug_do( 255 272 if( TL_GET( this_thread ) != this->owner ) { 256 273 abort( "Destroyed monitor %p has inconsistent owner, expected %p got %p.\n", this, TL_GET( this_thread ), this->owner); 257 274 } 258 if( this->recursion != 1 ) {275 if( this->recursion != 1 && !join ) { 259 276 abort( "Destroyed monitor %p has %d outstanding nested calls.\n", this, this->recursion - 1); 260 277 } 261 278 ) 279 280 this->owner = ($thread*)(1 | (uintptr_t)this->owner); 262 281 } 263 282 … … 307 326 } 308 327 328 // Join a thread 329 forall( dtype T | is_thread(T) ) 330 T & join( T & this ) { 331 $monitor * m = get_monitor(this); 332 void (*dtor)(T& mutex this) = ^?{}; 333 monitor_dtor_guard_t __guard = { &m, (fptr_t)dtor, true }; 334 { 335 return this; 336 } 337 } 338 309 339 // Enter multiple monitor 310 340 // relies on the monitor array being sorted … … 366 396 // Ctor for monitor guard 367 397 // Sorts monitors before entering 368 void ?{}( monitor_dtor_guard_t & this, $monitor * m [], fptr_t func ) {398 void ?{}( monitor_dtor_guard_t & this, $monitor * m [], fptr_t func, bool join ) { 369 399 // optimization 370 400 $thread * thrd = TL_GET( this_thread ); … … 376 406 this.prev = thrd->monitors; 377 407 408 // Save whether we are in a join or not 409 this.join = join; 410 378 411 // Update thread context (needed for conditions) 379 412 (thrd->monitors){m, 1, func}; 380 413 381 __dtor_enter( this.m, func );414 __dtor_enter( this.m, func, join ); 382 415 } 383 416 … … 385 418 void ^?{}( monitor_dtor_guard_t & this ) { 386 419 // Leave the monitors in order 387 __dtor_leave( this.m );420 __dtor_leave( this.m, this.join ); 388 421 389 422 // Restore thread context -
libcfa/src/concurrency/monitor.hfa
rc402739 r2724b4e 53 53 $monitor * m; 54 54 __monitor_group_t prev; 55 bool join; 55 56 }; 56 57 57 void ?{}( monitor_dtor_guard_t & this, $monitor ** m, void (*func)() );58 void ?{}( monitor_dtor_guard_t & this, $monitor ** m, void (*func)(), bool join ); 58 59 void ^?{}( monitor_dtor_guard_t & this ); 59 60 -
libcfa/src/concurrency/thread.hfa
rc402739 r2724b4e 106 106 void sleep( Duration duration ); 107 107 108 //---------- 109 // join 110 forall( dtype T | is_thread(T) ) 111 T & join( T & this ); 112 108 113 // Local Variables: // 109 114 // mode: c // -
src/AST/Convert.cpp
rc402739 r2724b4e 1162 1162 } 1163 1163 1164 const ast::Type * postvisit( const ast:: ReferenceToType * old, ReferenceToType * ty ) {1164 const ast::Type * postvisit( const ast::BaseInstType * old, ReferenceToType * ty ) { 1165 1165 ty->forall = get<TypeDecl>().acceptL( old->forall ); 1166 1166 ty->parameters = get<Expression>().acceptL( old->params ); … … 2521 2521 } 2522 2522 2523 void postvisit( const ReferenceToType * old, ast:: ReferenceToType * ty ) {2523 void postvisit( const ReferenceToType * old, ast::BaseInstType * ty ) { 2524 2524 ty->forall = GET_ACCEPT_V( forall, TypeDecl ); 2525 2525 ty->params = GET_ACCEPT_V( parameters, Expr ); -
src/AST/Fwd.hpp
rc402739 r2724b4e 107 107 class QualifiedType; 108 108 class FunctionType; 109 class ReferenceToType;109 class BaseInstType; 110 110 template<typename decl_t> class SueInstType; 111 111 using StructInstType = SueInstType<StructDecl>; -
src/AST/GenericSubstitution.cpp
rc402739 r2724b4e 42 42 private: 43 43 // make substitution for generic type 44 void makeSub( const ReferenceToType * ty ) {44 void makeSub( const BaseInstType * ty ) { 45 45 visit_children = false; 46 46 const AggregateDecl * aggr = ty->aggr(); -
src/AST/Node.cpp
rc402739 r2724b4e 266 266 template class ast::ptr_base< ast::FunctionType, ast::Node::ref_type::weak >; 267 267 template class ast::ptr_base< ast::FunctionType, ast::Node::ref_type::strong >; 268 template class ast::ptr_base< ast:: ReferenceToType, ast::Node::ref_type::weak >;269 template class ast::ptr_base< ast:: ReferenceToType, ast::Node::ref_type::strong >;268 template class ast::ptr_base< ast::BaseInstType, ast::Node::ref_type::weak >; 269 template class ast::ptr_base< ast::BaseInstType, ast::Node::ref_type::strong >; 270 270 template class ast::ptr_base< ast::StructInstType, ast::Node::ref_type::weak >; 271 271 template class ast::ptr_base< ast::StructInstType, ast::Node::ref_type::strong >; -
src/AST/Pass.hpp
rc402739 r2724b4e 118 118 119 119 // Versions of the above for older compilers. 120 template< typename... Args > 120 121 static void run( std::list< ptr<Decl> > & decls ) { 121 122 Pass<core_t> visitor; … … 123 124 } 124 125 125 static auto read( Node const * node ) { 126 template< typename node_type, typename... Args > 127 static auto read( node_type const * node ) { 126 128 Pass<core_t> visitor; 127 Node const * temp = node->accept( visitor );129 node_type const * temp = node->accept( visitor ); 128 130 assert( temp == node ); 129 131 return visitor.get_result(); -
src/AST/Print.cpp
rc402739 r2724b4e 270 270 } 271 271 272 void preprint( const ast:: ReferenceToType * node ) {272 void preprint( const ast::BaseInstType * node ) { 273 273 print( node->forall ); 274 274 print( node->attributes ); -
src/AST/SymbolTable.cpp
rc402739 r2724b4e 313 313 if ( ! expr->result ) continue; 314 314 const Type * resTy = expr->result->stripReferences(); 315 auto aggrType = dynamic_cast< const ReferenceToType * >( resTy );315 auto aggrType = dynamic_cast< const BaseInstType * >( resTy ); 316 316 assertf( aggrType, "WithStmt expr has non-aggregate type: %s", 317 317 toString( expr->result ).c_str() ); … … 654 654 if ( dwt->name == "" ) { 655 655 const Type * t = dwt->get_type()->stripReferences(); 656 if ( auto rty = dynamic_cast<const ReferenceToType *>( t ) ) {656 if ( auto rty = dynamic_cast<const BaseInstType *>( t ) ) { 657 657 if ( ! dynamic_cast<const StructInstType *>(rty) 658 658 && ! dynamic_cast<const UnionInstType *>(rty) ) continue; -
src/AST/Type.cpp
rc402739 r2724b4e 124 124 } 125 125 126 // --- ReferenceToType127 128 void ReferenceToType::initWithSub( const ReferenceToType & o, Pass< ForallSubstitutor > & sub ) {126 // --- BaseInstType 127 128 void BaseInstType::initWithSub( const BaseInstType & o, Pass< ForallSubstitutor > & sub ) { 129 129 ParameterizedType::initWithSub( o, sub ); // initialize substitution 130 130 params = sub.core( o.params ); // apply to parameters 131 131 } 132 132 133 ReferenceToType::ReferenceToType( const ReferenceToType & o )133 BaseInstType::BaseInstType( const BaseInstType & o ) 134 134 : ParameterizedType( o.qualifiers, copy( o.attributes ) ), params(), name( o.name ), 135 135 hoistType( o.hoistType ) { … … 138 138 } 139 139 140 std::vector<readonly<Decl>> ReferenceToType::lookup( const std::string& name ) const {140 std::vector<readonly<Decl>> BaseInstType::lookup( const std::string& name ) const { 141 141 assertf( aggr(), "Must have aggregate to perform lookup" ); 142 142 … … 153 153 SueInstType<decl_t>::SueInstType( 154 154 const decl_t * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as ) 155 : ReferenceToType( b->name, q, move(as) ), base( b ) {}155 : BaseInstType( b->name, q, move(as) ), base( b ) {} 156 156 157 157 template<typename decl_t> … … 168 168 TraitInstType::TraitInstType( 169 169 const TraitDecl * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as ) 170 : ReferenceToType( b->name, q, move(as) ), base( b ) {}170 : BaseInstType( b->name, q, move(as) ), base( b ) {} 171 171 172 172 // --- TypeInstType 173 173 174 174 TypeInstType::TypeInstType( const TypeInstType & o ) 175 : ReferenceToType( o.name, o.qualifiers, copy( o.attributes ) ), base(), kind( o.kind ) {175 : BaseInstType( o.name, o.qualifiers, copy( o.attributes ) ), base(), kind( o.kind ) { 176 176 Pass< ForallSubstitutor > sub; 177 177 initWithSub( o, sub ); // initialize substitution -
src/AST/Type.hpp
rc402739 r2724b4e 329 329 330 330 /// base class for types that refer to types declared elsewhere (aggregates and typedefs) 331 class ReferenceToType : public ParameterizedType {331 class BaseInstType : public ParameterizedType { 332 332 protected: 333 333 /// Initializes forall and parameters based on substitutor 334 void initWithSub( const ReferenceToType & o, Pass< ForallSubstitutor > & sub );334 void initWithSub( const BaseInstType & o, Pass< ForallSubstitutor > & sub ); 335 335 public: 336 336 std::vector<ptr<Expr>> params; … … 338 338 bool hoistType = false; 339 339 340 ReferenceToType(340 BaseInstType( 341 341 const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} ) 342 342 : ParameterizedType(q, std::move(as)), params(), name(n) {} 343 343 344 ReferenceToType( const ReferenceToType & o );344 BaseInstType( const BaseInstType & o ); 345 345 346 346 /// Gets aggregate declaration this type refers to … … 350 350 351 351 private: 352 virtual ReferenceToType * clone() const override = 0;352 virtual BaseInstType * clone() const override = 0; 353 353 MUTATE_FRIEND 354 354 }; … … 356 356 // Common implementation for the SUE instance types. Not to be used directly. 357 357 template<typename decl_t> 358 class SueInstType final : public ReferenceToType {358 class SueInstType final : public BaseInstType { 359 359 public: 360 360 using base_type = decl_t; … … 363 363 SueInstType( 364 364 const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} ) 365 : ReferenceToType( n, q, std::move(as) ), base() {}365 : BaseInstType( n, q, std::move(as) ), base() {} 366 366 367 367 SueInstType( … … 388 388 389 389 /// An instance of a trait type. 390 class TraitInstType final : public ReferenceToType {390 class TraitInstType final : public BaseInstType { 391 391 public: 392 392 readonly<TraitDecl> base; … … 394 394 TraitInstType( 395 395 const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} ) 396 : ReferenceToType( n, q, std::move(as) ), base() {}396 : BaseInstType( n, q, std::move(as) ), base() {} 397 397 398 398 TraitInstType( … … 411 411 412 412 /// instance of named type alias (typedef or variable) 413 class TypeInstType final : public ReferenceToType {413 class TypeInstType final : public BaseInstType { 414 414 public: 415 415 readonly<TypeDecl> base; … … 419 419 const std::string& n, const TypeDecl * b, CV::Qualifiers q = {}, 420 420 std::vector<ptr<Attribute>> && as = {} ) 421 : ReferenceToType( n, q, std::move(as) ), base( b ), kind( b->kind ) {}421 : BaseInstType( n, q, std::move(as) ), base( b ), kind( b->kind ) {} 422 422 TypeInstType( const std::string& n, TypeDecl::Kind k, CV::Qualifiers q = {}, 423 423 std::vector<ptr<Attribute>> && as = {} ) 424 : ReferenceToType( n, q, std::move(as) ), base(), kind( k ) {}424 : BaseInstType( n, q, std::move(as) ), base(), kind( k ) {} 425 425 426 426 TypeInstType( const TypeInstType & o ); -
src/AST/TypeSubstitution.cpp
rc402739 r2724b4e 176 176 } 177 177 178 void TypeSubstitution::Substituter::handleAggregateType( const ReferenceToType * type ) {178 void TypeSubstitution::Substituter::handleAggregateType( const BaseInstType * type ) { 179 179 GuardValue( boundVars ); 180 180 // bind type variables from forall-qualifiers -
src/AST/TypeSubstitution.hpp
rc402739 r2724b4e 169 169 void previsit( const ParameterizedType * type ); 170 170 /// Records type variable bindings from forall-statements and instantiations of generic types 171 void handleAggregateType( const ReferenceToType * type );171 void handleAggregateType( const BaseInstType * type ); 172 172 173 173 void previsit( const StructInstType * aggregateUseType ); -
src/Concurrency/Keywords.cc
rc402739 r2724b4e 931 931 { 932 932 new SingleInit( new AddressExpr( new VariableExpr( monitors ) ) ), 933 new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone(), false ) ) 933 new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone(), false ) ), 934 new SingleInit( new ConstantExpr( Constant::from_bool( false ) ) ) 934 935 }, 935 936 noDesignators, -
src/ResolvExpr/CandidateFinder.cpp
rc402739 r2724b4e 816 816 /// Adds aggregate member interpretations 817 817 void addAggMembers( 818 const ast:: ReferenceToType * aggrInst, const ast::Expr * expr,818 const ast::BaseInstType * aggrInst, const ast::Expr * expr, 819 819 const Candidate & cand, const Cost & addedCost, const std::string & name 820 820 ) { … … 1263 1263 1264 1264 void postvisit( const ast::UntypedOffsetofExpr * offsetofExpr ) { 1265 const ast:: ReferenceToType * aggInst;1265 const ast::BaseInstType * aggInst; 1266 1266 if (( aggInst = offsetofExpr->type.as< ast::StructInstType >() )) ; 1267 1267 else if (( aggInst = offsetofExpr->type.as< ast::UnionInstType >() )) ; -
src/ResolvExpr/CurrentObject.cc
rc402739 r2724b4e 923 923 924 924 MemberIterator * createMemberIterator( const CodeLocation & loc, const Type * type ) { 925 if ( auto aggr = dynamic_cast< const ReferenceToType * >( type ) ) {925 if ( auto aggr = dynamic_cast< const BaseInstType * >( type ) ) { 926 926 if ( auto sit = dynamic_cast< const StructInstType * >( aggr ) ) { 927 927 return new StructIterator{ loc, sit }; … … 932 932 dynamic_cast< const EnumInstType * >( type ) 933 933 || dynamic_cast< const TypeInstType * >( type ), 934 "Encountered unhandled ReferenceToType in createMemberIterator: %s",934 "Encountered unhandled BaseInstType in createMemberIterator: %s", 935 935 toString( type ).c_str() ); 936 936 return new SimpleIterator{ loc, type }; … … 965 965 DesignatorChain & d = *dit; 966 966 PRINT( std::cerr << "____actual: " << t << std::endl; ) 967 if ( auto refType = dynamic_cast< const ReferenceToType * >( t ) ) {967 if ( auto refType = dynamic_cast< const BaseInstType * >( t ) ) { 968 968 // concatenate identical field names 969 969 for ( const Decl * mem : refType->lookup( nexpr->name ) ) { -
src/ResolvExpr/Resolver.cc
rc402739 r2724b4e 1259 1259 const ast::ThrowStmt * previsit( const ast::ThrowStmt * ); 1260 1260 const ast::CatchStmt * previsit( const ast::CatchStmt * ); 1261 const ast::CatchStmt * postvisit( const ast::CatchStmt * ); 1261 1262 const ast::WaitForStmt * previsit( const ast::WaitForStmt * ); 1262 1263 … … 1491 1492 1492 1493 const ast::CatchStmt * Resolver_new::previsit( const ast::CatchStmt * catchStmt ) { 1493 // TODO: This will need a fix for the decl/cond scoping problem. 1494 // Until we are very sure this invarent (ifs that move between passes have thenPart) 1495 // holds, check it. This allows a check for when to decode the mangling. 1496 if ( auto ifStmt = catchStmt->body.as<ast::IfStmt>() ) { 1497 assert( ifStmt->thenPart ); 1498 } 1499 // Encode the catchStmt so the condition can see the declaration. 1494 1500 if ( catchStmt->cond ) { 1495 ast::ptr< ast::Type > boolType = new ast::BasicType{ ast::BasicType::Bool }; 1496 catchStmt = ast::mutate_field( 1497 catchStmt, &ast::CatchStmt::cond, 1498 findSingleExpression( catchStmt->cond, boolType, symtab ) ); 1501 ast::CatchStmt * stmt = mutate( catchStmt ); 1502 stmt->body = new ast::IfStmt( stmt->location, stmt->cond, nullptr, stmt->body ); 1503 stmt->cond = nullptr; 1504 return stmt; 1505 } 1506 return catchStmt; 1507 } 1508 1509 const ast::CatchStmt * Resolver_new::postvisit( const ast::CatchStmt * catchStmt ) { 1510 // Decode the catchStmt so everything is stored properly. 1511 const ast::IfStmt * ifStmt = catchStmt->body.as<ast::IfStmt>(); 1512 if ( nullptr != ifStmt && nullptr == ifStmt->thenPart ) { 1513 assert( ifStmt->cond ); 1514 assert( ifStmt->elsePart ); 1515 ast::CatchStmt * stmt = ast::mutate( catchStmt ); 1516 stmt->cond = ifStmt->cond; 1517 stmt->body = ifStmt->elsePart; 1518 // ifStmt should be implicately deleted here. 1519 return stmt; 1499 1520 } 1500 1521 return catchStmt; -
src/SymTab/Mangler.cc
rc402739 r2724b4e 437 437 private: 438 438 void mangleDecl( const ast::DeclWithType *declaration ); 439 void mangleRef( const ast:: ReferenceToType *refType, std::string prefix );439 void mangleRef( const ast::BaseInstType *refType, std::string prefix ); 440 440 441 441 void printQualifiers( const ast::Type *type ); … … 560 560 } 561 561 562 void Mangler_new::mangleRef( const ast:: ReferenceToType * refType, std::string prefix ) {562 void Mangler_new::mangleRef( const ast::BaseInstType * refType, std::string prefix ) { 563 563 printQualifiers( refType ); 564 564 -
src/SymTab/Validate.cc
rc402739 r2724b4e 960 960 } 961 961 962 static bool isNonParameterAttribute( Attribute * attr ) { 963 static const std::vector<std::string> bad_names = { 964 "aligned", "__aligned__", 965 }; 966 for ( auto name : bad_names ) { 967 if ( name == attr->name ) { 968 return true; 969 } 970 } 971 return false; 972 } 973 962 974 Type * ReplaceTypedef::postmutate( TypeInstType * typeInst ) { 963 975 // instances of typedef types will come here. If it is an instance … … 968 980 ret->location = typeInst->location; 969 981 ret->get_qualifiers() |= typeInst->get_qualifiers(); 970 // attributes are not carried over from typedef to function parameters/return values 971 if ( ! inFunctionType ) { 972 ret->attributes.splice( ret->attributes.end(), typeInst->attributes ); 973 } else { 974 deleteAll( ret->attributes ); 975 ret->attributes.clear(); 976 } 982 // GCC ignores certain attributes if they arrive by typedef, this mimics that. 983 if ( inFunctionType ) { 984 ret->attributes.remove_if( isNonParameterAttribute ); 985 } 986 ret->attributes.splice( ret->attributes.end(), typeInst->attributes ); 977 987 // place instance parameters on the typedef'd type 978 988 if ( ! typeInst->parameters.empty() ) { … … 1508 1518 } 1509 1519 1510 void checkGenericParameters( const ast:: ReferenceToType * inst ) {1520 void checkGenericParameters( const ast::BaseInstType * inst ) { 1511 1521 for ( const ast::Expr * param : inst->params ) { 1512 1522 if ( ! dynamic_cast< const ast::TypeExpr * >( param ) ) { -
tests/Makefile.am
rc402739 r2724b4e 38 38 # since automake doesn't have support for CFA we have to 39 39 AM_CFLAGS = $(if $(test), 2> $(test), ) \ 40 -fdebug-prefix-map=$(abspath ${abs_srcdir})= \ 41 -fdebug-prefix-map=/tmp= \ 40 42 -g \ 41 43 -Wall \ … … 110 112 % : %.cfa $(CFACCBIN) 111 113 $(CFACOMPILETEST) -c -o $(abspath ${@}).o 112 $(CFACCLOCAL) $( $(shell echo "${@}_FLAGSLD" | sed 's/-\|\//_/g')) $(abspath ${@}).o -o $(abspath ${@})114 $(CFACCLOCAL) $(if $(test), 2> $(test), ) $($(shell echo "${@}_FLAGSLD" | sed 's/-\|\//_/g')) ${@}.o -o $(abspath ${@}) 113 115 114 116 # implicit rule for c++ test … … 137 139 # CUSTOM TARGET 138 140 #------------------------------------------------------------------------------ 141 # tests that just validate syntax 142 expression : expression.cfa $(CFACCBIN) 143 $(CFACOMPILETEST) -c -fsyntax-only 2> $(abspath ${@}) 144 139 145 # expected failures 140 146 # use custom target since they require a custom define and custom dependencies -
tests/pybin/tools.py
rc402739 r2724b4e 120 120 return None 121 121 122 file = open(file, mode )122 file = open(file, mode, encoding="latin-1") # use latin-1 so all chars mean something. 123 123 exitstack.push(file) 124 124 return file -
tests/test.py
rc402739 r2724b4e 207 207 else: 208 208 if os.stat(out_file).st_size < 1048576: 209 with open (out_file, "r" ) as myfile:209 with open (out_file, "r", encoding='latin-1') as myfile: # use latin-1 so all chars mean something. 210 210 error = myfile.read() 211 211 else:
Note: See TracChangeset
for help on using the changeset viewer.