Changes in / [732b406:3a32b3a]


Ignore:
Files:
25 added
12 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/exception.c

    r732b406 r3a32b3a  
    8585        __cfadbg_print_safe(exception, "Throwing resumption exception\n");
    8686
    87         __attribute__((cleanup(reset_top_resume)))
    88         struct __cfaehm_try_resume_node * original_head = context->top_resume;
    89         struct __cfaehm_try_resume_node * current = context->top_resume;
    90 
    91         for ( ; current ; current = current->next) {
    92                 context->top_resume = current->next;
    93                 if (current->handler(except)) {
    94                         return;
     87        {
     88                __attribute__((cleanup(reset_top_resume)))
     89                struct __cfaehm_try_resume_node * original_head = context->top_resume;
     90                struct __cfaehm_try_resume_node * current = context->top_resume;
     91
     92                for ( ; current ; current = current->next) {
     93                        context->top_resume = current->next;
     94                        if (current->handler(except)) {
     95                                return;
     96                        }
    9597                }
    96         }
     98        } // End the search and return to the top of the stack.
    9799
    98100        // No handler found, fall back to the default operation.
  • libcfa/src/iostream.cfa

    r732b406 r3a32b3a  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jun 19 16:15:34 2020
    13 // Update Count     : 1019
     12// Last Modified On : Mon Jul  6 08:49:48 2020
     13// Update Count     : 1064
    1414//
    1515
     
    3030} // extern "C"
    3131
    32 #include <bitmanip.hfa>                                                                 // fms
     32#include <bitmanip.hfa>                                                                 // high1
    3333
    3434
     
    168168
    169169        static void base10_128( ostype & os, unsigned int128 val ) {
    170                 if ( val > UINT64_MAX ) {
     170                if ( val > P10_UINT64 ) {
    171171                        base10_128( os, val / P10_UINT64 );                     // recursive
    172172                        fmt( os, "%.19lu", (uint64_t)(val % P10_UINT64) );
     
    455455
    456456// Default prefix for non-decimal prints is 0b, 0, 0x.
    457 #define IntegralFMTImpl( T, CODE, IFMTNP, IFMTP ) \
     457#define IntegralFMTImpl( T, IFMTNP, IFMTP ) \
    458458forall( dtype ostype | ostream( ostype ) ) { \
    459459        ostype & ?|?( ostype & os, _Ostream_Manip(T) f ) { \
     
    506506                        if ( f.flags.left && spaces > 0 ) fmt( os, "%*s", spaces, " " ); \
    507507                        return os; \
    508                 } /* if  */ \
     508                } /* if */ \
    509509\
    510510                char fmtstr[sizeof(IFMTP)];                                             /* sizeof includes '\0' */ \
     
    516516                if ( ! f.flags.nobsdp ) { fmtstr[star] = '#'; star -= 1; } \
    517517                if ( f.flags.left ) { fmtstr[star] = '-'; star -= 1; } \
    518                 if ( f.flags.sign && f.base == CODE ) { fmtstr[star] = '+'; star -= 1; } \
     518                if ( f.flags.sign ) { fmtstr[star] = '+'; star -= 1; } \
    519519                if ( f.flags.pad0 && ! f.flags.pc ) { fmtstr[star] = '0'; star -= 1; } \
    520520                fmtstr[star] = '%'; \
     
    522522                if ( ! f.flags.pc ) {                                                   /* no precision */ \
    523523                        fmtstr[sizeof(IFMTNP)-2] = f.base;                      /* sizeof includes '\0' */ \
    524                         /* printf( "%s %c %c\n", &fmtstr[star], f.base, CODE ); */ \
     524                        /* printf( "%s %c\n", &fmtstr[star], f.base ); */ \
    525525                        fmt( os, &fmtstr[star], f.wd, f.val ); \
    526526                } else {                                                                                /* precision */ \
    527527                        fmtstr[sizeof(IFMTP)-2] = f.base;                       /* sizeof includes '\0' */ \
    528                         /* printf( "%s %c %c\n", &fmtstr[star], f.base, CODE ); */ \
     528                        /* printf( "%s %c\n", &fmtstr[star], f.base ); */ \
    529529                        fmt( os, &fmtstr[star], f.wd, f.pc, f.val ); \
    530530                } /* if */ \
     
    534534} // distribution
    535535
    536 IntegralFMTImpl( signed char, 'd', "%    *hh ", "%    *.*hh " )
    537 IntegralFMTImpl( unsigned char, 'u', "%    *hh ", "%    *.*hh " )
    538 IntegralFMTImpl( signed short int, 'd', "%    *h ", "%    *.*h " )
    539 IntegralFMTImpl( unsigned short int, 'u', "%    *h ", "%    *.*h " )
    540 IntegralFMTImpl( signed int, 'd', "%    * ", "%    *.* " )
    541 IntegralFMTImpl( unsigned int, 'u', "%    * ", "%    *.* " )
    542 IntegralFMTImpl( signed long int, 'd', "%    *l ", "%    *.*l " )
    543 IntegralFMTImpl( unsigned long int, 'u', "%    *l ", "%    *.*l " )
    544 IntegralFMTImpl( signed long long int, 'd', "%    *ll ", "%    *.*ll " )
    545 IntegralFMTImpl( unsigned long long int, 'u', "%    *ll ", "%    *.*ll " )
    546 
    547 
     536IntegralFMTImpl( signed char, "%    *hh ", "%    *.*hh " )
     537IntegralFMTImpl( unsigned char, "%    *hh ", "%    *.*hh " )
     538IntegralFMTImpl( signed short int, "%    *h ", "%    *.*h " )
     539IntegralFMTImpl( unsigned short int, "%    *h ", "%    *.*h " )
     540IntegralFMTImpl( signed int, "%    * ", "%    *.* " )
     541IntegralFMTImpl( unsigned int, "%    * ", "%    *.* " )
     542IntegralFMTImpl( signed long int, "%    *l ", "%    *.*l " )
     543IntegralFMTImpl( unsigned long int, "%    *l ", "%    *.*l " )
     544IntegralFMTImpl( signed long long int, "%    *ll ", "%    *.*ll " )
     545IntegralFMTImpl( unsigned long long int, "%    *ll ", "%    *.*ll " )
     546
     547#if 0
    548548#if defined( __SIZEOF_INT128__ )
    549549// Default prefix for non-decimal prints is 0b, 0, 0x.
     
    663663IntegralFMTImpl128( unsigned int128, unsigned, 'u', "%    *ll ", "%    *.*ll " )
    664664#endif // __SIZEOF_INT128__
     665#endif // 0
     666
     667#if 1
     668#if defined( __SIZEOF_INT128__ )
     669// Default prefix for non-decimal prints is 0b, 0, 0x.
     670forall( dtype ostype | ostream( ostype ) )
     671static inline void base_128( ostype & os, unsigned int128 val, unsigned int128 power, _Ostream_Manip(uint64_t) & f, unsigned int maxdig, unsigned int bits, unsigned int cnt = 0 ) {
     672        int wd = 1;                                                                                     // f.wd is never 0 because 0 implies left-pad
     673        if ( val > power ) {                                                            // subdivide value into printable 64-bit values
     674                base_128( os, val / power, power, f, maxdig, bits, cnt + 1 ); // recursive
     675                f.val = val % power;
     676                if ( cnt == 1 && f.flags.left ) { wd = f.wd; f.wd = maxdig; } // copy f.wd and reset for printing middle chunk
     677                (ostype &)(os | f);
     678                if ( cnt == 1 ) {
     679                        if ( f.flags.left ) { wd -= maxdig; f.wd = wd < 0 ? 1 : wd; } // update and restore f.wd for printing end chunk
     680                        sepOff( os );                                                           // no seperator between chunks
     681                } // if
     682        } else {                                                                                        // print start chunk
     683                f.val = val;
     684                // f.pc is unsigned => use wd
     685                if ( f.flags.pc && f.pc > maxdig * cnt ) { wd = f.pc - maxdig * cnt; f.pc = wd < 0 ? 0 : wd; }
     686                else { f.flags.pc = false; f.pc = 0; }
     687
     688                if ( ! f.flags.left ) {                                                 // right justify
     689                        wd = f.wd - maxdig * cnt;
     690                        f.wd = wd < 0 ? 1 : wd;
     691                        wd = maxdig;
     692                } else {                                                                                // left justify
     693                        if ( cnt != 0 ) {                                                       // value >= 2^64 ?
     694                                unsigned int dig, bs = 0;
     695                                // compute size of prefix digits and base
     696                                if ( f.base == 'd' || f.base == 'u' ) { // no base prefix
     697                                        dig = ceil( log10( f.val ) );           // use floating-point
     698                                        if ( f.base == 'd' && (f.flags.neg || f.flags.sign) ) bs = 1; // sign ?
     699                                } else {
     700                                        dig = ceiling( high1( f.val ), bits );
     701                                        if ( ! f.flags.nobsdp ) {                       // base prefix ?
     702                                                if ( f.base == 'o' ) {
     703                                                        // 0 prefix for octal is not added for precision with leading zero
     704                                                        if ( f.pc <= dig ) bs = 1;      // 1 character prefix
     705                                                } else bs = 2;                                  // 2 character prefix
     706                                        } // if
     707                                } // if
     708                                wd = f.wd - (f.pc > dig ? f.pc : dig) - bs; // precision > leading digits ?
     709                                if ( wd < 0 ) wd = 1;
     710                                f.wd = 1;
     711                        } // if
     712                        // all manipulators handled implicitly for value < 2^64
     713                } // if
     714                // prior checks ensure wd not negative
     715
     716                if ( f.flags.neg ) f.val = -f.val;
     717                (ostype &)(os | f);
     718
     719                // remaining middle and end chunks are padded with 0s on the left
     720                if ( ! f.flags.left ) { f.flags.pad0 = true; f.flags.pc = false; } // left pad with 0s
     721                else { f.pc = maxdig; f.flags.pc = true; }              // left pad with precision
     722
     723                if ( cnt != 0 ) sepOff( os );                                   // no seperator between chunks
     724                f.wd = wd;                                                                              // reset f.wd for next chunk
     725                f.flags.sign = false;                                                   // no leading +/- sign
     726                f.flags.nobsdp = true;                                                  // no leading base prefix
     727        } // if
     728} // base_128
     729
     730#define IntegralFMTImpl128( T ) \
     731forall( dtype ostype | ostream( ostype ) ) { \
     732        ostype & ?|?( ostype & os, _Ostream_Manip(T) f ) { \
     733                _Ostream_Manip(uint64_t) fmt; \
     734                fmt.[wd, pc, base, all] = f.[wd, pc, base, all]; \
     735                if ( f.base == 'b' | f.base == 'B' ) { \
     736                        base_128( os, f.val, (unsigned int128)1 << 64, fmt, 64, 1 ); \
     737                } else if ( f.base == 'o' ) { \
     738                        base_128( os, f.val, (unsigned int128)1 << 63, fmt, 21, 3 ); \
     739                } else if ( f.base == 'd' || f.base == 'u' ) { \
     740                        if ( f.base == 'd' && f.val < 0 ) { f.val = -f.val; fmt.flags.neg = true; } \
     741                        base_128( os, f.val, (unsigned int128)10_000_000_000_000_000_000UL, fmt, 19, 0 ); \
     742                } else { \
     743                        base_128( os, f.val, (unsigned int128)1 << 64, fmt, 16, 4 ); \
     744                } /* if */ \
     745                return os; \
     746        } /* ?|? */ \
     747        void ?|?( ostype & os, _Ostream_Manip(T) f ) { (ostype &)(os | f); ends( os ); } \
     748} // distribution
     749
     750IntegralFMTImpl128( int128 )
     751IntegralFMTImpl128( unsigned int128 )
     752#endif // __SIZEOF_INT128__
     753#endif // 0
    665754
    666755// *********************************** floating point ***********************************
  • libcfa/src/iostream.hfa

    r732b406 r3a32b3a  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jun 19 16:15:56 2020
    13 // Update Count     : 338
     12// Last Modified On : Sat Jul  4 18:31:48 2020
     13// Update Count     : 343
    1414//
    1515
     
    166166                unsigned char all;
    167167                struct {
     168                        unsigned char neg:1;                                            // val is negative
    168169                        unsigned char pc:1;                                                     // precision specified
    169170                        unsigned char left:1;                                           // left justify
     
    370371
    371372static inline {
    372         _Istream_Char ignore( const char c ) { return (_Istream_Char)@{ true }; }
     373        _Istream_Char ignore( const char ) { return (_Istream_Char)@{ true }; }
    373374        _Istream_Char & ignore( _Istream_Char & fmt ) { fmt.ignore = true; return fmt; }
    374375} // distribution
    375376forall( dtype istype | istream( istype ) ) istype & ?|?( istype & is, _Istream_Char f );
    376377
    377 forall( otype T )
     378forall( dtype T | sized( T ) )
    378379struct _Istream_Manip {
    379380        T & val;                                                                                        // polymorphic base-type
  • src/GenPoly/Specialize.cc

    r732b406 r3a32b3a  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Dec 13 23:40:49 2019
    13 // Update Count     : 32
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thr Jul  2 17:42:00 2020
     13// Update Count     : 33
    1414//
    1515
     
    4242
    4343namespace GenPoly {
    44         struct Specialize final : public WithConstTypeSubstitution, public WithStmtsToAdd, public WithVisitorRef<Specialize> {
     44        struct Specialize final : public WithConstTypeSubstitution,
     45                        public WithDeclsToAdd, public WithVisitorRef<Specialize> {
    4546                Expression * postmutate( ApplicationExpr *applicationExpr );
    4647                Expression * postmutate( CastExpr *castExpr );
     
    248249                } // if
    249250
    250                 // handle any specializations that may still be present
    251                 std::string oldParamPrefix = paramPrefix;
    252                 paramPrefix += "p";
    253                 // save stmtsToAddBefore in oldStmts
    254                 std::list< Statement* > oldStmts;
    255                 oldStmts.splice( oldStmts.end(), stmtsToAddBefore );
    256                 appExpr->acceptMutator( *visitor );
    257                 paramPrefix = oldParamPrefix;
    258                 // write any statements added for recursive specializations into the thunk body
    259                 thunkFunc->statements->kids.splice( thunkFunc->statements->kids.end(), stmtsToAddBefore );
    260                 // restore oldStmts into stmtsToAddBefore
    261                 stmtsToAddBefore.splice( stmtsToAddBefore.end(), oldStmts );
     251                // Handle any specializations that may still be present.
     252                {
     253                        std::string oldParamPrefix = paramPrefix;
     254                        paramPrefix += "p";
     255                        std::list< Declaration * > oldDecls;
     256                        oldDecls.splice( oldDecls.end(), declsToAddBefore );
     257
     258                        appExpr->acceptMutator( *visitor );
     259                        // Write recursive specializations into the thunk body.
     260                        for ( Declaration * decl : declsToAddBefore ) {
     261                                thunkFunc->statements->kids.push_back( new DeclStmt( decl ) );
     262                        }
     263
     264                        declsToAddBefore = std::move( oldDecls );
     265                        paramPrefix = oldParamPrefix;
     266                }
    262267
    263268                // add return (or valueless expression) to the thunk
     
    270275                thunkFunc->statements->kids.push_back( appStmt );
    271276
    272                 // add thunk definition to queue of statements to add
    273                 stmtsToAddBefore.push_back( new DeclStmt( thunkFunc ) );
     277                // Add the thunk definition (converted to DeclStmt if appproprate).
     278                declsToAddBefore.push_back( thunkFunc );
    274279                // return address of thunk function as replacement expression
    275280                return new AddressExpr( new VariableExpr( thunkFunc ) );
  • src/Parser/ParseNode.h

    r732b406 r3a32b3a  
    1010// Created On       : Sat May 16 13:28:16 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Feb  7 17:56:02 2020
    13 // Update Count     : 891
     12// Last Modified On : Mon Jul  6 09:33:32 2020
     13// Update Count     : 892
    1414//
    1515
     
    8686class InitializerNode : public ParseNode {
    8787  public:
    88         InitializerNode( ExpressionNode *, bool aggrp = false,  ExpressionNode * des = nullptr );
     88        InitializerNode( ExpressionNode *, bool aggrp = false, ExpressionNode * des = nullptr );
    8989        InitializerNode( InitializerNode *, bool aggrp = false, ExpressionNode * des = nullptr );
    9090        InitializerNode( bool isDelete );
  • tests/copyfile.cfa

    r732b406 r3a32b3a  
    1010// Created On       : Fri Jun 19 13:44:05 2020
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jun 19 17:58:03 2020
    13 // Update Count     : 4
     12// Last Modified On : Sun Jul  5 11:27:43 2020
     13// Update Count     : 5
    1414//
    1515
     
    2222
    2323        try {
    24                 choose ( argc ) {
     24                choose ( argc ) {                                                               // terminate if command-line errors
    2525                  case 2, 3:
    2626                        open( in, argv[1] );                                            // open input file first as output creates file
    2727                        if ( argc == 3 ) open( out, argv[2] );          // do not create output unless input opens
    2828                  case 1: ;                                                                             // use default files
    29                   default:
     29                  default:                                                                              // wrong number of options
    3030                        exit | "Usage" | argv[0] | "[ input-file (default stdin) [ output-file (default stdout) ] ]";
    3131                } // choose
  • tests/exceptions/.expect/defaults.txt

    r732b406 r3a32b3a  
    33jump default handler.
    44Catch unhandled_exception.
     5cross terminate throw
     6cross terminate default
     7cross terminate catch
     8cross resume throw
     9cross resume default
     10cross resume catch
  • tests/exceptions/defaults.cfa

    r732b406 r3a32b3a  
    3030                throwResume (log_message){(char *)"Should be printed.\n"};
    3131        } catchResume (log_message * this) {
    32                 printf(this->virtual_table->msg(this));
     32                printf("%s", this->virtual_table->msg(this));
    3333        }
    3434        // But we don't have to:
     
    6969}
    7070
     71TRIVIAL_EXCEPTION(second);
     72
     73void cross_test(void) {
     74        void defaultTerminationHandler(first &) {
     75                printf("cross terminate default\n");
     76                throw (second){};
     77        }
     78        void defaultResumptionHandler(first &) {
     79                printf("cross resume default\n");
     80                throwResume (second){};
     81        }
     82        try {
     83                printf("cross terminate throw\n");
     84                throw (first){};
     85        } catch (second *) {
     86                printf("cross terminate catch\n");
     87        }
     88        try {
     89                printf("cross resume throw\n");
     90                throwResume (first){};
     91        } catchResume (second *) {
     92                printf("cross resume catch\n");
     93        }
     94}
     95
    7196int main(int argc, char * argv[]) {
    7297        log_test();
    7398        jump_test();
    7499        unhandled_test();
     100        cross_test();
    75101}
  • tests/manipulatorsOutput3.cfa

    r732b406 r3a32b3a  
    1313    sout | sign(x);
    1414    sout | nl;
    15 #if 1
     15
    1616    sout | bin(x);
    1717    sout | upcase(bin(x));
     
    124124    sout | nl;
    125125
    126    
     126
     127    // extras
     128    sout | "extras";
    127129    sout | bin(divisor);
    128130    sout | upcase(bin(divisor));
     
    140142    sout | left(sign(wd(0,40, divisor))) | 'X';
    141143    printf( "%-+1.40dX\n", 123456789 );
    142 #endif // 0
     144
     145    int128 i128;
     146    unsigned int128 ui128;
     147
     148    i128 = -10;
     149    for ( 25 ) {
     150        sout | left( sign( wd( 20, i128 ) ) ) | left( wd( 20, hex( i128 ) ) ) | left( wd( 20, oct( i128 ) ) );
     151        sout | left( wd( 20, bin( i128 ) ) );
     152        i128 += 1;
     153    }
     154    sout | nl;
     155
     156    i128 = 0x7fffffffffffffff;
     157    i128 <<= 64;
     158    i128 += 0xfffffffffffffffa;
     159
     160    for ( 20 ) {
     161        sout | i128;
     162        sout | left( sign( wd( 45, i128 ) ) ) | left( wd( 45, hex( i128 ) ) ) | left( wd( 45, oct( i128 ) ) );
     163        sout | left( wd( 45, bin( i128 ) ) );
     164        i128 += 1;
     165    }
     166    sout | nl;
     167
     168    ui128 = 0x7fffffffffffffff;
     169    ui128 <<= 64;
     170    ui128 += 0xfffffffffffffffa;
     171   
     172    for ( 20 ) {
     173        sout | ui128;
     174        ui128 += 1;
     175    }
     176    sout | nl;
     177
     178    ui128 = 0xffffffffffffffff;
     179    ui128 <<= 64;
     180    ui128 += 0xfffffffffffffffa;
     181   
     182    for ( 20 ) {
     183        sout | ui128;
     184        ui128 += 1;
     185    }
    143186}
  • tests/pybin/test_run.py

    r732b406 r3a32b3a  
    6969                        else :                                          text = "FAILED with code %d" % retcode
    7070
    71                 text += "    C%s - R%s" % (cls.fmtDur(duration[0]), cls.fmtDur(duration[1]))
     71                text += "    C%s - R%s" % (fmtDur(duration[0]), fmtDur(duration[1]))
    7272                return text
    73 
    74         @staticmethod
    75         def fmtDur( duration ):
    76                 if duration :
    77                         hours, rem = divmod(duration, 3600)
    78                         minutes, rem = divmod(rem, 60)
    79                         seconds, millis = divmod(rem, 1)
    80                         return "%2d:%02d.%03d" % (minutes, seconds, millis * 1000)
    81                 return " n/a"
  • tests/pybin/tools.py

    r732b406 r3a32b3a  
    387387                while True:
    388388                        yield i.next(max(expire - time.time(), 0))
     389
     390def fmtDur( duration ):
     391        if duration :
     392                hours, rem = divmod(duration, 3600)
     393                minutes, rem = divmod(rem, 60)
     394                seconds, millis = divmod(rem, 1)
     395                return "%2d:%02d.%03d" % (minutes, seconds, millis * 1000)
     396        return " n/a"
  • tests/test.py

    r732b406 r3a32b3a  
    361361
    362362                # for each build configurations, run the test
    363                 for arch, debug, install in itertools.product(settings.all_arch, settings.all_debug, settings.all_install):
    364                         settings.arch    = arch
    365                         settings.debug   = debug
    366                         settings.install = install
    367 
    368                         # filter out the tests for a different architecture
    369                         # tests are the same across debug/install
    370                         local_tests = settings.arch.filter( tests )
    371                         options.jobs, forceJobs = job_count( options, local_tests )
    372                         settings.update_make_cmd(forceJobs, options.jobs)
    373 
    374                         # check the build configuration works
    375                         settings.validate()
    376 
    377                         # print configuration
    378                         print('%s %i tests on %i cores (%s:%s)' % (
    379                                 'Regenerating' if settings.generating else 'Running',
    380                                 len(local_tests),
    381                                 options.jobs,
    382                                 settings.arch.string,
    383                                 settings.debug.string
    384                         ))
    385 
    386                         # otherwise run all tests and make sure to return the correct error code
    387                         failed = run_tests(local_tests, options.jobs)
    388                         if failed:
    389                                 result = 1
    390                                 if not settings.continue_:
    391                                         break
    392 
    393 
     363                with Timed() as total_dur:
     364                        for arch, debug, install in itertools.product(settings.all_arch, settings.all_debug, settings.all_install):
     365                                settings.arch    = arch
     366                                settings.debug   = debug
     367                                settings.install = install
     368
     369                                # filter out the tests for a different architecture
     370                                # tests are the same across debug/install
     371                                local_tests = settings.arch.filter( tests )
     372                                options.jobs, forceJobs = job_count( options, local_tests )
     373                                settings.update_make_cmd(forceJobs, options.jobs)
     374
     375                                # check the build configuration works
     376                                settings.validate()
     377
     378                                # print configuration
     379                                print('%s %i tests on %i cores (%s:%s)' % (
     380                                        'Regenerating' if settings.generating else 'Running',
     381                                        len(local_tests),
     382                                        options.jobs,
     383                                        settings.arch.string,
     384                                        settings.debug.string
     385                                ))
     386
     387                                # otherwise run all tests and make sure to return the correct error code
     388                                failed = run_tests(local_tests, options.jobs)
     389                                if failed:
     390                                        result = 1
     391                                        if not settings.continue_:
     392                                                break
     393
     394                print('Tests took %s' % fmtDur( total_dur.duration ))
    394395                sys.exit( failed )
Note: See TracChangeset for help on using the changeset viewer.