Changes in / [e874605:93d2219]


Ignore:
Files:
22 added
2 deleted
41 edited

Legend:

Unmodified
Added
Removed
  • benchmark/io/http/worker.hfa

    re874605 r93d2219  
    22
    33#include <iofwd.hfa>
    4 #include <queueLockFree.hfa>
     4#include <containers/lockfree.hfa>
    55#include <thread.hfa>
    66
  • doc/theses/mike_brooks_MMath/programs/hello-md.cfa

    re874605 r93d2219  
    11#include "array.hfa"
    2 
    3 
    4 trait ix( C &, E &, ztype(N) ) {
    5     E & ?[?]( C &, ptrdiff_t );
    6     void __taglen( tag(C), tag(N) );
    7 };
    8 
    9 forall( ztype(Zn), ztype(S), Timmed &, Tbase & )
    10 void __taglen( tag(arpk(Zn, S, Timmed, Tbase)), tag(Zn) ) {}
    112
    123
     
    3829
    3930
    40 forall( ztype( N ) )
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40forall( [N] )
    4141void print1d_cstyle( array(float, N) & c );
    4242
    43 forall( C &, ztype( N ) | ix( C, float, N ) )
     43forall( [N], C & | ar( C, float, N ) )
    4444void print1d( C & c );
    4545
     
    5858
    5959
    60 forall( ztype( N ) )
     60forall( [N] )
    6161void print1d_cstyle( array(float, N) & c ) {
    62     for( i; z(N) ) {
     62    for( i; N ) {
    6363        printf("%.1f  ", c[i]);
    6464    }
     
    7878
    7979
    80 forall( C &, ztype( N ) | ix( C, float, N ) )
     80forall( [N], C & | ar( C, float, N ) )
    8181void print1d( C & c ) {
    82     for( i; z(N) ) {
     82    for( i; N ) {
    8383        printf("%.1f  ", c[i]);
    8484    }
     
    9999
    100100
    101 void fill( array(float, Z(5), Z(7)) & a ) {
     101void fill( array(float, 5, 7) & a ) {
    102102    for ( i; (ptrdiff_t) 5 ) {
    103103        for ( j; 7 ) {
    104             a[[i,j]] = 1.0 * i + 0.1 * j;
    105             printf("%.1f  ", a[[i,j]]);
     104            a[i,j] = 1.0 * i + 0.1 * j;
     105            printf("%.1f  ", a[i,j]);
    106106        }
    107107        printf("\n");
     
    118118
    119119
    120 array( float, Z(5), Z(7) ) a;
     120array( float, 5, 7 ) a;
    121121fill(a);
    122122/*
     
    148148
    149149
    150 print1d( a[[ 2, all ]] );  // 2.0  2.1  2.2  2.3  2.4  2.5  2.6
    151 print1d( a[[ all, 3 ]] );  // 0.3  1.3  2.3  3.3  4.3
     150print1d( a[ 2, all ] );  // 2.0  2.1  2.2  2.3  2.4  2.5  2.6
     151print1d( a[ all, 3 ] );  // 0.3  1.3  2.3  3.3  4.3
    152152
    153153
    154154
    155 print1d_cstyle( a[[ 2, all ]] );
     155print1d_cstyle( a[ 2, all ] );
    156156
    157157
     
    161161
    162162
    163 #ifdef SHOWERR1
     163#ifdef SHOW_ERROR_1
    164164
    165 print1d_cstyle( a[[ all, 2 ]] );  // bad
     165print1d_cstyle( a[ all, 2 ] );  // bad
    166166
    167167#endif
  • doc/theses/thierry_delisle_PhD/thesis/text/front.tex

    re874605 r93d2219  
    161161Thanks to Andrew Beach, Michael Brooks, Colby Parsons, Mubeen Zulfiqar, Fangren Yu and Jiada Liang for their work on the \CFA project as well as all the discussions which have helped me concretize the ideas in this thesis.
    162162
    163 Finally, I acknowledge that this has been possible thanks to the financial help offered by the David R. Cheriton School of Computer Science and the corporate partnership with Huawei Ltd.
     163Finally, I acknowledge that this has been possible thanks to the financial help offered by the David R. Cheriton School of Computer Science, the corporate partnership with Huawei Ltd. and the Natural Sciences and Engineering Research Council.
    164164\cleardoublepage
    165165
  • libcfa/src/Makefile.am

    re874605 r93d2219  
    6262        containers/array.hfa \
    6363        containers/list.hfa \
    64         containers/queueLockFree.hfa \
    65         containers/stackLockFree.hfa \
     64        containers/lockfree.hfa \
    6665        containers/string_sharectx.hfa \
    6766        containers/vector2.hfa \
     
    127126
    128127thread_libsrc = ${inst_thread_headers_src} ${inst_thread_headers_src:.hfa=.cfa} \
     128        interpose_thread.cfa \
    129129        bits/signal.hfa \
    130130        concurrency/clib/cfathread.cfa \
     
    145145        concurrency/stats.cfa \
    146146        concurrency/stats.hfa \
    147         concurrency/stats.hfa
     147        concurrency/stats.hfa \
     148        concurrency/pthread.cfa
    148149
    149150else
  • libcfa/src/concurrency/clib/cfathread.cfa

    re874605 r93d2219  
    172172
    173173                pthread_attr_t attr;
    174                 if (int ret = pthread_attr_init(&attr); 0 != ret) {
     174                if (int ret = __cfaabi_pthread_attr_init(&attr); 0 != ret) {
    175175                        abort | "failed to create master epoll thread attr: " | ret | strerror(ret);
    176176                }
    177177
    178                 if (int ret = pthread_create(&master_poller, &attr, master_epoll, 0p); 0 != ret) {
     178                if (int ret = __cfaabi_pthread_create(&master_poller, &attr, master_epoll, 0p); 0 != ret) {
    179179                        abort | "failed to create master epoll thread: " | ret | strerror(ret);
    180180                }
  • libcfa/src/concurrency/invoke.h

    re874605 r93d2219  
    214214
    215215                #if defined( __CFA_WITH_VERIFY__ )
     216                        struct processor * volatile executing;
    216217                        void * canary;
    217218                #endif
  • libcfa/src/concurrency/io.cfa

    re874605 r93d2219  
    610610                if( we ) {
    611611                        sigval_t value = { PREEMPT_IO };
    612                         pthread_sigqueue(ctx->proc->kernel_thread, SIGUSR1, value);
     612                        __cfaabi_pthread_sigqueue(ctx->proc->kernel_thread, SIGUSR1, value);
    613613                }
    614614
  • libcfa/src/concurrency/io/setup.cfa

    re874605 r93d2219  
    344344        //      iopoll.run = false;
    345345        //      sigval val = { 1 };
    346         //      pthread_sigqueue( iopoll.thrd, SIGUSR1, val );
     346        //      __cfaabi_pthread_sigqueue( iopoll.thrd, SIGUSR1, val );
    347347
    348348        //      // Make sure all this is done
  • libcfa/src/concurrency/kernel.cfa

    re874605 r93d2219  
    321321                /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) < ((uintptr_t)__get_stack(thrd_dst->curr_cor)->base ) || thrd_dst->curr_cor == proc_cor || thrd_dst->corctx_flag, "ERROR : Destination thread$ %p has been corrupted.\n StackPointer too small.\n", thrd_dst ); // add escape condition if we are setting up the processor
    322322                /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) > ((uintptr_t)__get_stack(thrd_dst->curr_cor)->limit) || thrd_dst->curr_cor == proc_cor || thrd_dst->corctx_flag, "ERROR : Destination thread$ %p has been corrupted.\n StackPointer too large.\n", thrd_dst ); // add escape condition if we are setting up the processor
     323                /* paranoid */ verify( __atomic_exchange_n( &thrd_dst->executing, this, __ATOMIC_SEQ_CST) == 0p );
    323324                /* paranoid */ verify( 0x0D15EA5E0D15EA5Ep == thrd_dst->canary );
    324325
     
    332333
    333334                /* paranoid */ verify( 0x0D15EA5E0D15EA5Ep == thrd_dst->canary );
     335                /* paranoid */ verify( __atomic_exchange_n( &thrd_dst->executing, 0p, __ATOMIC_SEQ_CST) == this );
    334336                /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) > ((uintptr_t)__get_stack(thrd_dst->curr_cor)->limit) || thrd_dst->corctx_flag, "ERROR : Destination thread$ %p has been corrupted.\n StackPointer too large.\n", thrd_dst );
    335337                /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) < ((uintptr_t)__get_stack(thrd_dst->curr_cor)->base ) || thrd_dst->corctx_flag, "ERROR : Destination thread$ %p has been corrupted.\n StackPointer too small.\n", thrd_dst );
     338                /* paranoid */ verify( thrd_dst->state != Halted );
    336339                /* paranoid */ verify( thrd_dst->context.SP );
    337                 /* paranoid */ verify( thrd_dst->curr_cluster == this->cltr );
    338340                /* paranoid */ verify( kernelTLS().this_thread == thrd_dst );
    339341                /* paranoid */ verify( ! __preemption_enabled() );
  • libcfa/src/concurrency/kernel.hfa

    re874605 r93d2219  
    160160// P9_EMBEDDED( processor, dlink(processor) )
    161161static inline tytagref( dlink(processor), dlink(processor) ) ?`inner( processor & this ) {
    162     dlink(processor) & b = this.link;
    163     tytagref( dlink(processor), dlink(processor) ) result = { b };
    164     return result;
     162        dlink(processor) & b = this.link;
     163        tytagref( dlink(processor), dlink(processor) ) result = { b };
     164        return result;
    165165}
    166166
     
    269269                io_context_params params;
    270270        } io;
     271
     272        struct {
     273                struct processor ** procs;
     274                unsigned cnt;
     275        } managed;
    271276
    272277        #if !defined(__CFA_NO_STATISTICS__)
     
    298303static inline struct cluster   * active_cluster  () { return publicTLS_get( this_processor )->cltr; }
    299304
     305// set the number of internal processors
     306// these processors are in addition to any explicitly declared processors
     307unsigned set_concurrency( cluster & this, unsigned new_count );
     308
    300309#if !defined(__CFA_NO_STATISTICS__)
    301310        void print_stats_now( cluster & this, int flags );
  • libcfa/src/concurrency/kernel/private.hfa

    re874605 r93d2219  
    2020#endif
    2121
     22#include <signal.h>
     23
    2224#include "kernel.hfa"
    2325#include "thread.hfa"
     
    4850        #endif
    4951#endif
    50 
    5152// #define READYQ_USE_LINEAR_AVG
    5253#define READYQ_USE_LOGDBL_AVG
     
    6263#error must pick a scheme for averaging
    6364#endif
     65
     66extern "C" {
     67        __attribute__((visibility("protected"))) int __cfaabi_pthread_create(pthread_t *_thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
     68        __attribute__((visibility("protected"))) int __cfaabi_pthread_join(pthread_t _thread, void **retval);
     69        __attribute__((visibility("protected"))) pthread_t __cfaabi_pthread_self(void);
     70        __attribute__((visibility("protected"))) int __cfaabi_pthread_attr_init(pthread_attr_t *attr);
     71        __attribute__((visibility("protected"))) int __cfaabi_pthread_attr_destroy(pthread_attr_t *attr);
     72        __attribute__((visibility("protected"))) int __cfaabi_pthread_attr_setstack( pthread_attr_t *attr, void *stackaddr, size_t stacksize );
     73        __attribute__((visibility("protected"))) int __cfaabi_pthread_attr_getstacksize( const pthread_attr_t *attr, size_t *stacksize );
     74        __attribute__((visibility("protected"))) int __cfaabi_pthread_sigqueue(pthread_t _thread, int sig, const union sigval value);
     75        __attribute__((visibility("protected"))) int __cfaabi_pthread_sigmask( int how, const sigset_t *set, sigset_t *oset);
     76}
    6477
    6578//-----------------------------------------------------------------------------
  • libcfa/src/concurrency/kernel/startup.cfa

    re874605 r93d2219  
    1616#define __cforall_thread__
    1717#define _GNU_SOURCE
     18
     19// #define __CFA_DEBUG_PRINT_RUNTIME_CORE__
    1820
    1921// C Includes
     
    222224                ( this.runner ){};
    223225                init( this, "Main Processor", *mainCluster, 0p );
    224                 kernel_thread = pthread_self();
     226                kernel_thread = __cfaabi_pthread_self();
    225227
    226228                runner{ &this };
     
    283285}
    284286
     287extern "C"{
     288        void pthread_delete_kernel_threads_();
     289}
     290
     291
    285292static void __kernel_shutdown(void) {
    286293        if(!cfa_main_returned) return;
     294
     295        //delete kernel threads for pthread_concurrency
     296        pthread_delete_kernel_threads_();
     297
    287298        /* paranoid */ verify( __preemption_enabled() );
    288299        disable_interrupts();
     
    327338
    328339                /* paranoid */ verify( this.do_terminate == true );
    329                 __cfaabi_dbg_print_safe("Kernel : destroyed main processor context %p\n", &runner);
     340                __cfadbg_print_safe(runtime_core, "Kernel : destroyed main processor context %p\n", &runner);
    330341        }
    331342
     
    388399        (proc->runner){ proc, &info };
    389400
    390         __cfaabi_dbg_print_safe("Coroutine : created stack %p\n", get_coroutine(proc->runner)->stack.storage);
     401        __cfadbg_print_safe(runtime_core, "Coroutine : created stack %p\n", get_coroutine(proc->runner)->stack.storage);
    391402
    392403        //Set global state
     
    520531        random_state = __global_random_mask ? __global_random_prime : __global_random_prime ^ rdtscl();
    521532        #if defined( __CFA_WITH_VERIFY__ )
     533                executing = 0p;
    522534                canary = 0x0D15EA5E0D15EA5Ep;
    523535        #endif
     
    652664        io.params = io_params;
    653665
     666        managed.procs = 0p;
     667        managed.cnt = 0;
     668
    654669        doregister(this);
    655670
     
    667682
    668683void ^?{}(cluster & this) libcfa_public {
     684        set_concurrency( this, 0 );
     685
    669686        destroy(this.io.arbiter);
    670687
     
    777794        pthread_attr_t attr;
    778795
    779         check( pthread_attr_init( &attr ), "pthread_attr_init" ); // initialize attribute
     796        check( __cfaabi_pthread_attr_init( &attr ), "pthread_attr_init" ); // initialize attribute
    780797
    781798        size_t stacksize = max( PTHREAD_STACK_MIN, DEFAULT_STACK_SIZE );
     
    804821        #endif
    805822
    806         check( pthread_attr_setstack( &attr, stack, stacksize ), "pthread_attr_setstack" );
    807         check( pthread_create( pthread, &attr, start, arg ), "pthread_create" );
     823        check( __cfaabi_pthread_attr_setstack( &attr, stack, stacksize ), "pthread_attr_setstack" );
     824        check( __cfaabi_pthread_create( pthread, &attr, start, arg ), "pthread_create" );
    808825        return stack;
    809826}
    810827
    811828void __destroy_pthread( pthread_t pthread, void * stack, void ** retval ) {
    812         int err = pthread_join( pthread, retval );
     829        int err = __cfaabi_pthread_join( pthread, retval );
    813830        if( err != 0 ) abort("KERNEL ERROR: joining pthread %p caused error %s\n", (void*)pthread, strerror(err));
    814831
     
    816833                pthread_attr_t attr;
    817834
    818                 check( pthread_attr_init( &attr ), "pthread_attr_init" ); // initialize attribute
     835                check( __cfaabi_pthread_attr_init( &attr ), "pthread_attr_init" ); // initialize attribute
    819836
    820837                size_t stacksize;
    821838                // default stack size, normally defined by shell limit
    822                 check( pthread_attr_getstacksize( &attr, &stacksize ), "pthread_attr_getstacksize" );
     839                check( __cfaabi_pthread_attr_getstacksize( &attr, &stacksize ), "pthread_attr_getstacksize" );
    823840                assert( stacksize >= PTHREAD_STACK_MIN );
    824841                stacksize += __page_size;
     
    838855}
    839856
     857unsigned set_concurrency( cluster & this, unsigned new ) libcfa_public {
     858        unsigned old = this.managed.cnt;
     859
     860        __cfadbg_print_safe(runtime_core, "Kernel : resizing cluster from %u to %u\n", old, (unsigned)new);
     861
     862        // Delete all the old unneeded procs
     863        if(old > new) for(i; (unsigned)new ~ old) {
     864                __cfadbg_print_safe(runtime_core, "Kernel : destroying %u\n", i);
     865                delete( this.managed.procs[i] );
     866        }
     867
     868        // Allocate new array (uses realloc and memcpies the data)
     869        this.managed.procs = alloc( new, this.managed.procs`realloc );
     870        this.managed.cnt = new;
     871
     872        // Create the desired new procs
     873        if(old < new) for(i; old ~ new) {
     874                __cfadbg_print_safe(runtime_core, "Kernel : constructing %u\n", i);
     875                (*(this.managed.procs[i] = alloc())){ this };
     876        }
     877
     878        // return the old count
     879        return old;
     880}
     881
    840882#if defined(__CFA_WITH_VERIFY__)
    841883static bool verify_fwd_bck_rng(void) {
  • libcfa/src/concurrency/locks.hfa

    re874605 r93d2219  
    2121
    2222#include "bits/weakso_locks.hfa"
    23 #include "containers/queueLockFree.hfa"
     23#include "containers/lockfree.hfa"
    2424#include "containers/list.hfa"
    2525
     
    423423}
    424424
    425 static inline size_t on_wait(simple_owner_lock & this) with(this) { 
     425static inline size_t on_wait(simple_owner_lock & this) with(this) {
    426426        lock( lock __cfaabi_dbg_ctx2 );
    427427        /* paranoid */ verifyf( owner != 0p, "Attempt to release lock %p that isn't held", &this );
  • libcfa/src/concurrency/preemption.cfa

    re874605 r93d2219  
    352352        sigset_t oldset;
    353353        int ret;
    354         ret = pthread_sigmask(0, ( const sigset_t * ) 0p, &oldset);  // workaround trac#208: cast should be unnecessary
     354        ret = __cfaabi_pthread_sigmask(0, ( const sigset_t * ) 0p, &oldset);  // workaround trac#208: cast should be unnecessary
    355355        if(ret != 0) { abort("ERROR sigprocmask returned %d", ret); }
    356356
     
    385385        sigaddset( &mask, sig );
    386386
    387         if ( pthread_sigmask( SIG_UNBLOCK, &mask, 0p ) == -1 ) {
     387        if ( __cfaabi_pthread_sigmask( SIG_UNBLOCK, &mask, 0p ) == -1 ) {
    388388            abort( "internal error, pthread_sigmask" );
    389389        }
     
    396396        sigaddset( &mask, sig );
    397397
    398         if ( pthread_sigmask( SIG_BLOCK, &mask, 0p ) == -1 ) {
     398        if ( __cfaabi_pthread_sigmask( SIG_BLOCK, &mask, 0p ) == -1 ) {
    399399                abort( "internal error, pthread_sigmask" );
    400400        }
     
    404404static void preempt( processor * this ) {
    405405        sigval_t value = { PREEMPT_NORMAL };
    406         pthread_sigqueue( this->kernel_thread, SIGUSR1, value );
     406        __cfaabi_pthread_sigqueue( this->kernel_thread, SIGUSR1, value );
    407407}
    408408
     
    415415        sigset_t oldset;
    416416        int ret;
    417         ret = pthread_sigmask(0, ( const sigset_t * ) 0p, &oldset);  // workaround trac#208: cast should be unnecessary
     417        ret = __cfaabi_pthread_sigmask(0, ( const sigset_t * ) 0p, &oldset);  // workaround trac#208: cast should be unnecessary
    418418        if(ret != 0) { abort("ERROR sigprocmask returned %d", ret); }
    419419
     
    434434        sigset_t oldset;
    435435        int ret;
    436         ret = pthread_sigmask(0, ( const sigset_t * ) 0p, &oldset);  // workaround trac#208: cast should be unnecessary
     436        ret = __cfaabi_pthread_sigmask(0, ( const sigset_t * ) 0p, &oldset);  // workaround trac#208: cast should be unnecessary
    437437        if(ret != 0) { abort("ERROR sigprocmask returned %d", ret); }
    438438
     
    505505        sigval val;
    506506        val.sival_int = 0;
    507         pthread_sigqueue( alarm_thread, SIGALRM, val );
     507        __cfaabi_pthread_sigqueue( alarm_thread, SIGALRM, val );
    508508
    509509        // Wait for the preemption thread to finish
     
    579579        static_assert( sizeof( sigset_t ) == sizeof( cxt->uc_sigmask ), "Expected cxt->uc_sigmask to be of sigset_t" );
    580580        #endif
    581         if ( pthread_sigmask( SIG_SETMASK, (sigset_t *)&(cxt->uc_sigmask), 0p ) == -1 ) {
     581        if ( __cfaabi_pthread_sigmask( SIG_SETMASK, (sigset_t *)&(cxt->uc_sigmask), 0p ) == -1 ) {
    582582                abort( "internal error, sigprocmask" );
    583583        }
     
    607607        sigset_t mask;
    608608        sigfillset(&mask);
    609         if ( pthread_sigmask( SIG_BLOCK, &mask, 0p ) == -1 ) {
     609        if ( __cfaabi_pthread_sigmask( SIG_BLOCK, &mask, 0p ) == -1 ) {
    610610            abort( "internal error, pthread_sigmask" );
    611611        }
  • libcfa/src/concurrency/thread.cfa

    re874605 r93d2219  
    5050        random_state = __global_random_mask ? __global_random_prime : __global_random_prime ^ rdtscl();
    5151        #if defined( __CFA_WITH_VERIFY__ )
     52                executing = 0p;
    5253                canary = 0x0D15EA5E0D15EA5Ep;
    5354        #endif
     
    177178
    178179//-----------------------------------------------------------------------------
     180bool migrate( thread$ * thrd, struct cluster & cl ) {
     181
     182        monitor$ * tmon = get_monitor(thrd);
     183        monitor$ * __monitors[] = { tmon };
     184        monitor_guard_t __guard = { __monitors, 1 };
     185
     186
     187        {
     188                // if nothing needs to be done, return false
     189                if( thrd->curr_cluster == &cl ) return false;
     190
     191                // are we migrating ourself?
     192                const bool local = thrd == active_thread();
     193
     194                /* paranoid */ verify( !local || &cl != active_cluster() );
     195                /* paranoid */ verify( !local || thrd->curr_cluster == active_cluster() );
     196                /* paranoid */ verify( !local || thrd->curr_cluster == active_processor()->cltr );
     197                /* paranoid */ verify( local || tmon->signal_stack.top->owner->waiting_thread == thrd );
     198                /* paranoid */ verify( local || tmon->signal_stack.top );
     199
     200                // make sure we aren't interrupted while doing this
     201                // not as important if we aren't local
     202                disable_interrupts();
     203
     204                // actually move the thread
     205                unregister( thrd->curr_cluster, *thrd );
     206                thrd->curr_cluster = &cl;
     207                doregister( thrd->curr_cluster, *thrd );
     208
     209                // restore interrupts
     210                enable_interrupts();
     211
     212                // if this is the local thread, we are still running on the old cluster
     213                if(local) yield();
     214
     215                /* paranoid */ verify( !local || &cl == active_cluster() );
     216                /* paranoid */ verify( !local || thrd->curr_cluster == active_cluster() );
     217                /* paranoid */ verify( !local || thrd->curr_cluster == active_processor()->cltr );
     218                /* paranoid */ verify(  local || tmon->signal_stack.top );
     219                /* paranoid */ verify(  local || tmon->signal_stack.top->owner->waiting_thread == thrd );
     220
     221                return true;
     222        }
     223}
     224
     225//-----------------------------------------------------------------------------
    179226#define GENERATOR LCG
    180227
  • libcfa/src/concurrency/thread.hfa

    re874605 r93d2219  
    132132
    133133//----------
     134// misc
     135bool migrate( thread$ * thrd, struct cluster & cl );
     136
     137forall( T & | is_thread(T) )
     138static inline bool migrate( T & mutex thrd, struct cluster & cl ) { return migrate( &(thread&)thrd, cl ); }
     139
     140
     141//----------
    134142// prng
    135143static inline {
  • libcfa/src/containers/array.hfa

    re874605 r93d2219  
     1#pragma once
     2
    13#include <assert.h>
    24
     
    1820    // About the choice of integral types offered as subscript overloads:
    1921    // Intent is to cover these use cases:
     22    //    a[0]                                                // i : zero_t
     23    //    a[1]                                                // i : one_t
     24    //    a[2]                                                // i : int
    2025    //    float foo( ptrdiff_t i ) { return a[i]; }           // i : ptrdiff_t
     26    //    float foo( size_t i ) { return a[i]; }              // i : size_t
    2127    //    forall( [N] ) ... for( i; N ) { total += a[i]; }    // i : typeof( sizeof(42) )
    2228    //    for( i; 5 ) { total += a[i]; }                      // i : int
     29    //
    2330    // It gets complicated by:
    2431    // -  CFA does overloading on concrete types, like int and unsigned int, not on typedefed
     
    2734    // -  Given bug of Trac #247, CFA gives sizeof expressions type unsigned long int, when it
    2835    //    should give them type size_t.
    29     //   
    30     //                          gcc -m32         cfa -m32 given bug         gcc -m64
     36    //
     37    //                          gcc -m32         cfa -m32 given bug         gcc -m64 (and cfa)
    3138    // ptrdiff_t                int              int                        long int
    3239    // size_t                   unsigned int     unsigned int               unsigned long int
    3340    // typeof( sizeof(42) )     unsigned int     unsigned long int          unsigned long int
    3441    // int                      int              int                        int
     42    //
     43    // So the solution must support types {zero_t, one_t, int, unsigned int, long int, unsigned long int}
     44    //
     45    // The solution cannot rely on implicit conversions (e.g. just have one overload for ptrdiff_t)
     46    // because assertion satisfaction requires types to match exacly.  Both higher-dimensional
     47    // subscripting and operations on slices use asserted subscript operators.  The test case
     48    // array-container/array-sbscr-cases covers the combinations.  Mike beleives that commenting out
     49    // any of the current overloads leads to one of those cases failing, either on 64- or 32-bit.
     50    // Mike is open to being shown a smaller set of overloads that still passes the test.
     51
     52    static inline Timmed & ?[?]( arpk(N, S, Timmed, Tbase) & a, zero_t ) {
     53        assert( 0 < N );
     54        return (Timmed &) a.strides[0];
     55    }
     56
     57    static inline Timmed & ?[?]( arpk(N, S, Timmed, Tbase) & a, one_t ) {
     58        assert( 1 < N );
     59        return (Timmed &) a.strides[1];
     60    }
    3561
    3662    static inline Timmed & ?[?]( arpk(N, S, Timmed, Tbase) & a, int i ) {
     
    3965    }
    4066
     67    static inline const Timmed & ?[?]( const arpk(N, S, Timmed, Tbase) & a, int i ) {
     68        assert( i < N );
     69        return (Timmed &) a.strides[i];
     70    }
     71
    4172    static inline Timmed & ?[?]( arpk(N, S, Timmed, Tbase) & a, unsigned int i ) {
    4273        assert( i < N );
     
    4475    }
    4576
     77    static inline const Timmed & ?[?]( const arpk(N, S, Timmed, Tbase) & a, unsigned int i ) {
     78        assert( i < N );
     79        return (Timmed &) a.strides[i];
     80    }
     81
    4682    static inline Timmed & ?[?]( arpk(N, S, Timmed, Tbase) & a, long int i ) {
    4783        assert( i < N );
     
    4985    }
    5086
     87    static inline const Timmed & ?[?]( const arpk(N, S, Timmed, Tbase) & a, long int i ) {
     88        assert( i < N );
     89        return (Timmed &) a.strides[i];
     90    }
     91
    5192    static inline Timmed & ?[?]( arpk(N, S, Timmed, Tbase) & a, unsigned long int i ) {
     93        assert( i < N );
     94        return (Timmed &) a.strides[i];
     95    }
     96
     97    static inline const Timmed & ?[?]( const arpk(N, S, Timmed, Tbase) & a, unsigned long int i ) {
    5298        assert( i < N );
    5399        return (Timmed &) a.strides[i];
     
    57103        return N;
    58104    }
     105
     106    static inline void __taglen( tag(arpk(N, S, Timmed, Tbase)), tag(N) ) {}
    59107
    60108    // workaround #226 (and array relevance thereof demonstrated in mike102/otype-slow-ndims.cfa)
     
    83131    // Make a FOREACH macro
    84132    #define FE_0(WHAT)
    85     #define FE_1(WHAT, X) WHAT(X) 
     133    #define FE_1(WHAT, X) WHAT(X)
    86134    #define FE_2(WHAT, X, ...) WHAT(X)FE_1(WHAT, __VA_ARGS__)
    87135    #define FE_3(WHAT, X, ...) WHAT(X)FE_2(WHAT, __VA_ARGS__)
     
    90138    //... repeat as needed
    91139
    92     #define GET_MACRO(_0,_1,_2,_3,_4,_5,NAME,...) NAME 
     140    #define GET_MACRO(_0,_1,_2,_3,_4,_5,NAME,...) NAME
    93141    #define FOR_EACH(action,...) \
    94142    GET_MACRO(_0,__VA_ARGS__,FE_5,FE_4,FE_3,FE_2,FE_1,FE_0)(action,__VA_ARGS__)
     
    115163}
    116164
    117 #else 
     165#else
    118166
    119167// Workaround form.  Listing all possibilities up to 4 dims.
     
    135183
    136184#endif
     185
     186// Available for users to work around Trac #265
     187// If `a[...0...]` isn't working, try `a[...ix0...]` instead.
     188
     189#define ix0 ((ptrdiff_t)0)
     190
     191
    137192
    138193//
     
    155210
    156211// Wrapper
    157 struct all_t {} all;
     212extern struct all_t {} all;
    158213forall( [N], S & | sized(S), Te &, result &, Tbase & | { tag(result) enq_( tag(Tbase), tag(N), tag(S), tag(Te) ); } )
    159214static inline result & ?[?]( arpk(N, S, Te, Tbase) & this, all_t ) {
     
    165220//
    166221
    167 trait ar(A &, Tv &) {
    168     Tv& ?[?]( A&, ptrdiff_t );
    169     size_t ?`len( A& );
    170 };
     222// desired:
     223// trait ar(A &, Tv &, [N]) {
     224//     Tv& ?[?]( A&, zero_t );
     225//     Tv& ?[?]( A&, one_t  );
     226//     Tv& ?[?]( A&, int    );
     227//                   ...
     228//     size_t ?`len( A& );
     229//     void __taglen( tag(C), tag(N) );
     230// };
     231
     232// working around N's not being accepted as arguments to traits
     233
     234#define ar(A, Tv, N) {                 \
     235    Tv& ?[?]( A&, zero_t );            \
     236    Tv& ?[?]( A&, one_t );             \
     237    Tv& ?[?]( A&, int );               \
     238    Tv& ?[?]( A&, unsigned int );      \
     239    Tv& ?[?]( A&, long int );          \
     240    Tv& ?[?]( A&, unsigned long int ); \
     241    size_t ?`len( A& );                \
     242    void __taglen( tag(A), tag(N) );   \
     243}
  • libcfa/src/device/cpu.cfa

    re874605 r93d2219  
    359359                int idxs = count_cache_indexes();
    360360
     361                // Do we actually have a cache?
     362                if(idxs == 0) {
     363                        // if not just fake the data structure, it makes things easier.
     364                        cpu_info.hthrd_count = cpus_c;
     365                        cpu_info.llc_count = 0;
     366                        struct cpu_map_entry_t * entries = alloc(cpu_info.hthrd_count);
     367                        for(i; cpu_info.hthrd_count) {
     368                                entries[i].self  = i;
     369                                entries[i].start = 0;
     370                                entries[i].count = cpu_info.hthrd_count;
     371                                entries[i].cache = 0;
     372                        }
     373                        cpu_info.llc_map = entries;
     374                        return;
     375                }
     376
    361377                // Count actual cache levels
    362378                unsigned cache_levels = 0;
    363379                unsigned llc = 0;
    364                 if (idxs != 0) {
    365                         unsigned char prev = -1u;
    366                         void first(unsigned idx, unsigned char level, const char * map, size_t len) {
    367                                 /* paranoid */ verifyf(level < prev, "Index %u of cpu 0 has cache levels out of order: %u then %u", idx, (unsigned)prev, (unsigned)level);
    368                                 llc = max(llc, level);
    369                                 prev = level;
    370                                 cache_levels++;
    371                         }
    372                         foreach_cacheidx(0, idxs, first);
    373                 }
     380
     381                unsigned char prev = -1u;
     382                void first(unsigned idx, unsigned char level, const char * map, size_t len) {
     383                        /* paranoid */ verifyf(level < prev, "Index %u of cpu 0 has cache levels out of order: %u then %u", idx, (unsigned)prev, (unsigned)level);
     384                        llc = max(llc, level);
     385                        prev = level;
     386                        cache_levels++;
     387                }
     388                foreach_cacheidx(0, idxs, first);
    374389
    375390                // Read in raw data
  • libcfa/src/heap.cfa

    re874605 r93d2219  
    211211#if BUCKETLOCK == SPINLOCK
    212212#elif BUCKETLOCK == LOCKFREE
    213 #include <stackLockFree.hfa>
     213#include <containers/lockfree.hfa>
    214214#else
    215215        #error undefined lock type for bucket lock
     
    505505                                freeLists[j].blockSize = bucketSizes[j];
    506506                        } // for
    507        
     507
    508508                        heapBuffer = 0p;
    509509                        heapReserve = 0;
  • libcfa/src/interpose.cfa

    re874605 r93d2219  
    4242
    4343typedef void (* generic_fptr_t)(void);
     44static generic_fptr_t do_interpose_symbol( void * library, const char symbol[], const char version[] ) {
     45        const char * error;
     46
     47        union { generic_fptr_t fptr; void * ptr; } originalFunc;
     48
     49        #if defined( _GNU_SOURCE )
     50                if ( version ) {
     51                        originalFunc.ptr = dlvsym( library, symbol, version );
     52                } else {
     53                        originalFunc.ptr = dlsym( library, symbol );
     54                }
     55        #else
     56                originalFunc.ptr = dlsym( library, symbol );
     57        #endif // _GNU_SOURCE
     58
     59        error = dlerror();
     60        if ( error ) abort( "interpose_symbol : internal error, %s\n", error );
     61
     62        return originalFunc.fptr;
     63}
     64
    4465static generic_fptr_t interpose_symbol( const char symbol[], const char version[] ) {
    4566        const char * error;
    4667
    4768        static void * library;
     69        static void * pthread_library;
    4870        if ( ! library ) {
    4971                #if defined( RTLD_NEXT )
     
    5880                #endif
    5981        } // if
    60 
    61         union { generic_fptr_t fptr; void * ptr; } originalFunc;
    62 
    63         #if defined( _GNU_SOURCE )
    64                 if ( version ) {
    65                         originalFunc.ptr = dlvsym( library, symbol, version );
    66                 } else {
    67                         originalFunc.ptr = dlsym( library, symbol );
    68                 }
    69         #else
    70                 originalFunc.ptr = dlsym( library, symbol );
    71         #endif // _GNU_SOURCE
    72 
    73         error = dlerror();
    74         if ( error ) abort( "interpose_symbol : internal error, %s\n", error );
    75 
    76         return originalFunc.fptr;
     82        if ( ! pthread_library ) {
     83                #if defined( RTLD_NEXT )
     84                        pthread_library = RTLD_NEXT;
     85                #else
     86                        // missing RTLD_NEXT => must hard-code library name, assuming libstdc++
     87                        pthread_library = dlopen( "libpthread.so", RTLD_LAZY );
     88                        error = dlerror();
     89                        if ( error ) {
     90                                abort( "interpose_symbol : failed to open libpthread, %s\n", error );
     91                        }
     92                #endif
     93        } // if
     94
     95        return do_interpose_symbol(library, symbol, version);
    7796}
    7897
     
    97116
    98117extern "C" {
     118        void __cfathreadabi_interpose_startup( generic_fptr_t (*do_interpose_symbol)( void * library, const char symbol[], const char version[] ) ) __attribute__((weak));
    99119        void __cfaabi_interpose_startup( void ) {
    100120                const char *version = 0p;
     
    108128                INTERPOSE_LIBC( exit , version );
    109129#pragma GCC diagnostic pop
     130
     131                if(__cfathreadabi_interpose_startup) __cfathreadabi_interpose_startup( do_interpose_symbol );
    110132
    111133                // As a precaution (and necessity), errors that result in termination are delivered on a separate stack because
  • libcfa/src/parseargs.cfa

    re874605 r93d2219  
    5050extern char ** cfa_args_envp __attribute__((weak));
    5151
    52 static void usage(char * cmd, cfa_option options[], size_t opt_count, const char * usage, FILE * out)  __attribute__ ((noreturn));
     52forall([N])
     53static void usage(char * cmd, const array( cfa_option, N ) & options, const char * usage, FILE * out)  __attribute__ ((noreturn));
    5354//-----------------------------------------------------------------------------
    5455// checking
    55 static void check_args(cfa_option options[], size_t opt_count) {
    56         for(i; opt_count) {
    57                 for(j; opt_count) {
     56forall([N])
     57static void check_args( const array( cfa_option, N ) & options ) {
     58        for(i; N) {
     59                for(j; N) {
    5860                        if(i == j) continue;
    5961
     
    7072//-----------------------------------------------------------------------------
    7173// Parsing args
    72 void parse_args( cfa_option options[], size_t opt_count, const char * usage, char ** & left ) {
    73         if( 0p != &cfa_args_argc ) {
    74                 parse_args(cfa_args_argc, cfa_args_argv, options, opt_count, usage, left );
    75         }
    76         else {
    77                 char * temp = "";
    78                 parse_args(0, &temp, options, opt_count, usage, left );
    79         }
    80 }
    81 
    82 void parse_args(
    83         int argc,
    84         char * argv[],
    85         cfa_option options[],
    86         size_t opt_count,
    87         const char * usage,
    88         char ** & left
    89 ) {
    90         check_args(options, opt_count);
    91 
    92         int maxv = 'h';
    93         char optstring[(opt_count * 3) + 2] = { '\0' };
    94         {
    95                 int idx = 0;
    96                 for(i; opt_count) {
    97                         if (options[i].short_name) {
    98                                 maxv = max(options[i].short_name, maxv);
    99                                 optstring[idx] = options[i].short_name;
    100                                 idx++;
    101                                 if(    ((intptr_t)options[i].parse) != ((intptr_t)parse_settrue)
    102                                 && ((intptr_t)options[i].parse) != ((intptr_t)parse_setfalse) ) {
    103                                         optstring[idx] = ':';
     74forall([opt_count]) {
     75        void parse_args( const array( cfa_option, opt_count ) & options, const char * usage, char ** & left ) {
     76                if( 0p != &cfa_args_argc ) {
     77                        parse_args(cfa_args_argc, cfa_args_argv, options, usage, left );
     78                }
     79                else {
     80                        char * temp = "";
     81                        parse_args(0, &temp, options, usage, left );
     82                }
     83        }
     84
     85        void parse_args(
     86                int argc,
     87                char * argv[],
     88                const array( cfa_option, opt_count ) & options,
     89                const char * usage,
     90                char ** & left
     91        ) {
     92                check_args(options);
     93
     94                int maxv = 'h';
     95                char optstring[(opt_count * 3) + 2] = { '\0' };
     96                {
     97                        int idx = 0;
     98                        for(i; opt_count) {
     99                                if (options[i].short_name) {
     100                                        maxv = max(options[i].short_name, maxv);
     101                                        optstring[idx] = options[i].short_name;
     102                                        idx++;
     103                                        if(    ((intptr_t)options[i].parse) != ((intptr_t)parse_settrue)
     104                                        && ((intptr_t)options[i].parse) != ((intptr_t)parse_setfalse) ) {
     105                                                optstring[idx] = ':';
     106                                                idx++;
     107                                        }
     108                                }
     109                        }
     110                        optstring[idx+0] = 'h';
     111                        optstring[idx+1] = '\0';
     112                }
     113
     114                struct option optarr[opt_count + 2];
     115                {
     116                        int idx = 0;
     117                        for(i; opt_count) {
     118                                if(options[i].long_name) {
     119                                        // we don't have the mutable keyword here, which is really what we would want
     120                                        int & val_ref = (int &)(const int &)options[i].val;
     121                                        val_ref = (options[i].short_name != '\0') ? ((int)options[i].short_name) : ++maxv;
     122
     123                                        optarr[idx].name = options[i].long_name;
     124                                        optarr[idx].flag = 0p;
     125                                        optarr[idx].val  = options[i].val;
     126                                        if(    ((intptr_t)options[i].parse) == ((intptr_t)parse_settrue)
     127                                        || ((intptr_t)options[i].parse) == ((intptr_t)parse_setfalse) ) {
     128                                                optarr[idx].has_arg = no_argument;
     129                                        } else {
     130                                                optarr[idx].has_arg = required_argument;
     131                                        }
    104132                                        idx++;
    105133                                }
    106134                        }
    107                 }
    108                 optstring[idx+0] = 'h';
    109                 optstring[idx+1] = '\0';
    110         }
    111 
    112         struct option optarr[opt_count + 2];
    113         {
    114                 int idx = 0;
    115                 for(i; opt_count) {
    116                         if(options[i].long_name) {
    117                                 options[i].val = (options[i].short_name != '\0') ? ((int)options[i].short_name) : ++maxv;
    118                                 optarr[idx].name = options[i].long_name;
    119                                 optarr[idx].flag = 0p;
    120                                 optarr[idx].val  = options[i].val;
    121                                 if(    ((intptr_t)options[i].parse) == ((intptr_t)parse_settrue)
    122                                     || ((intptr_t)options[i].parse) == ((intptr_t)parse_setfalse) ) {
    123                                         optarr[idx].has_arg = no_argument;
    124                                 } else {
    125                                         optarr[idx].has_arg = required_argument;
    126                                 }
    127                                 idx++;
     135                        optarr[idx+0].[name, has_arg, flag, val] = ["help", no_argument, 0, 'h'];
     136                        optarr[idx+1].[name, has_arg, flag, val] = [0, no_argument, 0, 0];
     137                }
     138
     139                FILE * out = stderr;
     140                NEXT_ARG:
     141                for() {
     142                        int idx = 0;
     143                        int opt = getopt_long(argc, argv, optstring, optarr, &idx);
     144                        switch(opt) {
     145                                case -1:
     146                                        if(&left != 0p) left = argv + optind;
     147                                        return;
     148                                case 'h':
     149                                        out = stdout;
     150                                case '?':
     151                                        usage(argv[0], options, usage, out);
     152                                default:
     153                                        for(i; opt_count) {
     154                                                if(opt == options[i].val) {
     155                                                        const char * arg = optarg ? optarg : "";
     156                                                        if( arg[0] == '=' ) { arg++; }
     157                                                        // work around for some weird bug
     158                                                        void * variable = options[i].variable;
     159                                                        bool (*parse_func)(const char *, void * ) = options[i].parse;
     160                                                        bool success = parse_func( arg, variable );
     161                                                        if(success) continue NEXT_ARG;
     162
     163                                                        fprintf(out, "Argument '%s' for option %c could not be parsed\n\n", arg, (char)opt);
     164                                                        usage(argv[0], options, usage, out);
     165                                                }
     166                                        }
     167                                        abort("Internal parse arg error\n");
    128168                        }
    129                 }
    130                 optarr[idx+0].[name, has_arg, flag, val] = ["help", no_argument, 0, 'h'];
    131                 optarr[idx+1].[name, has_arg, flag, val] = [0, no_argument, 0, 0];
    132         }
    133 
    134         FILE * out = stderr;
    135         NEXT_ARG:
    136         for() {
    137                 int idx = 0;
    138                 int opt = getopt_long(argc, argv, optstring, optarr, &idx);
    139                 switch(opt) {
    140                         case -1:
    141                                 if(&left != 0p) left = argv + optind;
    142                                 return;
    143                         case 'h':
    144                                 out = stdout;
    145                         case '?':
    146                                 usage(argv[0], options, opt_count, usage, out);
    147                         default:
    148                                 for(i; opt_count) {
    149                                         if(opt == options[i].val) {
    150                                                 const char * arg = optarg ? optarg : "";
    151                                                 if( arg[0] == '=' ) { arg++; }
    152                                                 bool success = options[i].parse( arg, options[i].variable );
    153                                                 if(success) continue NEXT_ARG;
    154 
    155                                                 fprintf(out, "Argument '%s' for option %c could not be parsed\n\n", arg, (char)opt);
    156                                                 usage(argv[0], options, opt_count, usage, out);
    157                                         }
    158                                 }
    159                                 abort("Internal parse arg error\n");
    160                 }
    161 
     169
     170                }
    162171        }
    163172}
     
    222231
    223232void print_args_usage(cfa_option options[], size_t opt_count, const char * usage, bool error)  __attribute__ ((noreturn)) {
    224         usage(cfa_args_argv[0], options, opt_count, usage, error ? stderr : stdout);
     233        const array( cfa_option, opt_count ) & arr = (const array( cfa_option, opt_count ) &) *options;
     234        usage(cfa_args_argv[0], arr, usage, error ? stderr : stdout);
    225235}
    226236
    227237void print_args_usage(int , char * argv[], cfa_option options[], size_t opt_count, const char * usage, bool error)  __attribute__ ((noreturn)) {
    228         usage(argv[0], options, opt_count, usage, error ? stderr : stdout);
    229 }
    230 
    231 static void usage(char * cmd, cfa_option options[], size_t opt_count, const char * help, FILE * out) __attribute__((noreturn)) {
     238        const array( cfa_option, opt_count ) & arr = (const array( cfa_option, opt_count ) &) *options;
     239        usage(argv[0], arr, usage, error ? stderr : stdout);
     240}
     241
     242forall( [N] ) {
     243        void print_args_usage( const array(cfa_option, N ) & options, const char * usage, bool error) {
     244                usage(cfa_args_argv[0], options, usage, error ? stderr : stdout);
     245        }
     246
     247        void print_args_usage(int argc, char * argv[], const array( cfa_option, N ) & options, const char * usage, bool error) {
     248                usage(argv[0], options, usage, error ? stderr : stdout);
     249        }
     250}
     251
     252forall([N])
     253static void usage(char * cmd, const array( cfa_option, N ) & options, const char * help, FILE * out) __attribute__((noreturn)) {
    232254        int width = 0;
    233255        {
    234                 for(i; opt_count) {
     256                for(i; N) {
    235257                        if(options[i].long_name) {
    236258                                int w = strlen(options[i].long_name);
     
    251273        fprintf(out, "Usage:\n  %s %s\n", cmd, help);
    252274
    253         for(i; opt_count) {
     275        for(i; N) {
    254276                printopt(out, width, max_width, options[i].short_name, options[i].long_name, options[i].help);
    255277        }
  • libcfa/src/parseargs.hfa

    re874605 r93d2219  
    1616#pragma once
    1717
     18#include <array.hfa>
     19
    1820struct cfa_option {
    19       int val; // reserved
    20       char short_name;
    21       const char * long_name;
    22       const char * help;
    23       void * variable;
    24       bool (*parse)(const char *, void * );
     21        int val; // reserved
     22        char short_name;
     23        const char * long_name;
     24        const char * help;
     25        void * variable;
     26        bool (*parse)(const char *, void * );
    2527};
    2628
     
    3133forall(T & | { bool parse(const char *, T & ); })
    3234static inline void ?{}( cfa_option & this, char short_name, const char * long_name, const char * help, T & variable ) {
    33       this.val        = 0;
    34       this.short_name = short_name;
    35       this.long_name  = long_name;
    36       this.help       = help;
    37       this.variable   = (void*)&variable;
    38       this.parse      = (bool (*)(const char *, void * ))parse;
     35        this.val        = 0;
     36        this.short_name = short_name;
     37        this.long_name  = long_name;
     38        this.help       = help;
     39        this.variable   = (void*)&variable;
     40        this.parse      = (bool (*)(const char *, void * ))parse;
    3941}
    4042
    4143forall(T &)
    4244static inline void ?{}( cfa_option & this, char short_name, const char * long_name, const char * help, T & variable, bool (*parse)(const char *, T & )) {
    43       this.val        = 0;
    44       this.short_name = short_name;
    45       this.long_name  = long_name;
    46       this.help       = help;
    47       this.variable   = (void*)&variable;
    48       this.parse      = (bool (*)(const char *, void * ))parse;
     45        this.val        = 0;
     46        this.short_name = short_name;
     47        this.long_name  = long_name;
     48        this.help       = help;
     49        this.variable   = (void*)&variable;
     50        this.parse      = (bool (*)(const char *, void * ))parse;
    4951}
    5052
     
    5254void parse_args( int argc, char * argv[], cfa_option options[], size_t opt_count, const char * usage, char ** & left );
    5355
     56forall( [N] ) {
     57        void parse_args( const array( cfa_option, N ) & options, const char * usage, char ** & left );
     58        void parse_args( int argc, char * argv[], const array( cfa_option, N ) & options, const char * usage, char ** & left );
     59}
     60
    5461void print_args_usage(cfa_option options[], size_t opt_count, const char * usage, bool error)  __attribute__ ((noreturn));
    5562void print_args_usage(int argc, char * argv[], cfa_option options[], size_t opt_count, const char * usage, bool error)  __attribute__ ((noreturn));
     63
     64forall( [N] ) {
     65        void print_args_usage( const array(cfa_option, N ) & options, const char * usage, bool error)  __attribute__ ((noreturn));
     66        void print_args_usage(int argc, char * argv[], const array( cfa_option, N ) & options, const char * usage, bool error)  __attribute__ ((noreturn));
     67}
    5668
    5769bool parse_yesno    (const char *, bool & );
  • src/AST/Type.cpp

    re874605 r93d2219  
    147147// --- TypeInstType
    148148
     149bool TypeInstType::operator==( const TypeInstType & other ) const {
     150        return base == other.base
     151                && formal_usage == other.formal_usage
     152                && expr_id == other.expr_id;
     153}
     154
    149155TypeInstType::TypeInstType( const TypeDecl * b,
    150156        CV::Qualifiers q, std::vector<ptr<Attribute>> && as )
     
    157163
    158164bool TypeInstType::isComplete() const { return base->sized; }
     165
     166std::string TypeInstType::TypeEnvKey::typeString() const {
     167        return std::string("_") + std::to_string(formal_usage)
     168                + "_" + std::to_string(expr_id) + "_" + base->name;
     169}
     170
     171bool TypeInstType::TypeEnvKey::operator==(
     172                const TypeInstType::TypeEnvKey & other ) const {
     173        return base == other.base
     174                && formal_usage == other.formal_usage
     175                && expr_id == other.expr_id;
     176}
     177
     178bool TypeInstType::TypeEnvKey::operator<(
     179                const TypeInstType::TypeEnvKey & other ) const {
     180        // TypeEnvKey ordering is an arbitrary total ordering.
     181        // It doesn't mean anything but allows for a sorting.
     182        if ( base < other.base ) {
     183                return true;
     184        } else if ( other.base < base ) {
     185                return false;
     186        } else if ( formal_usage < other.formal_usage ) {
     187                return true;
     188        } else if ( other.formal_usage < formal_usage ) {
     189                return false;
     190        } else {
     191                return expr_id < other.expr_id;
     192        }
     193}
    159194
    160195// --- TupleType
  • src/AST/Type.hpp

    re874605 r93d2219  
    408408
    409409                TypeEnvKey() = default;
    410                 TypeEnvKey(const TypeDecl * base, int formal_usage = 0, int expr_id = 0): base(base), formal_usage(formal_usage), expr_id(expr_id) {}
    411                 TypeEnvKey(const TypeInstType & inst): base(inst.base), formal_usage(inst.formal_usage), expr_id(inst.expr_id) {}
    412                 std::string typeString() const { return std::string("_") + std::to_string(formal_usage) + "_" + std::to_string(expr_id) + "_" + base->name; }
    413                 bool operator==(const TypeEnvKey & other) const { return base == other.base && formal_usage == other.formal_usage && expr_id == other.expr_id; }
     410                TypeEnvKey(const TypeDecl * base, int formal_usage = 0, int expr_id = 0)
     411                : base(base), formal_usage(formal_usage), expr_id(expr_id) {}
     412                TypeEnvKey(const TypeInstType & inst)
     413                : base(inst.base), formal_usage(inst.formal_usage), expr_id(inst.expr_id) {}
     414                std::string typeString() const;
     415                bool operator==(const TypeEnvKey & other) const;
     416                bool operator<(const TypeEnvKey & other) const;
    414417        };
    415418
    416         bool operator==(const TypeInstType & other) const { return base == other.base && formal_usage == other.formal_usage && expr_id == other.expr_id; }
     419        bool operator==(const TypeInstType & other) const;
    417420
    418421        TypeInstType(
  • src/AST/module.mk

    re874605 r93d2219  
    6767        AST/Util.cpp \
    6868        AST/Util.hpp \
     69        AST/Vector.hpp \
    6970        AST/Visitor.hpp
    7071
  • src/GenPoly/GenPoly.cc

    re874605 r93d2219  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Oct  7 15:25:00 2022
    13 // Update Count     : 16
     12// Last Modified On : Mon Oct 24 15:19:00 2022
     13// Update Count     : 17
    1414//
    1515
     
    194194
    195195        if ( auto inst = dynamic_cast< const ast::TypeInstType * >( type ) ) {
    196                 if ( typeVars.find( inst->typeString() ) != typeVars.end() ) return type;
     196                if ( typeVars.find( *inst ) != typeVars.end() ) return type;
    197197        } else if ( auto array = dynamic_cast< const ast::ArrayType * >( type ) ) {
    198198                return isPolyType( array->base, subst );
     
    227227
    228228        if ( auto inst = dynamic_cast<ast::TypeInstType const *>( type ) ) {
    229                 auto var = typeVars.find( inst->name );
     229                auto var = typeVars.find( *inst );
    230230                if ( var != typeVars.end() && var->second.isComplete ) {
    231231
     
    784784
    785785void addToTypeVarMap( const ast::TypeInstType * type, TypeVarMap & typeVars ) {
    786         typeVars.insert( type->typeString(), ast::TypeDecl::Data( type->base ) );
     786        typeVars.insert( *type, ast::TypeDecl::Data( type->base ) );
    787787}
    788788
     
    816816        }
    817817
    818 void printTypeVarMap( std::ostream &os, const TypeVarMap & typeVars ) {
    819         for ( auto const & pair : typeVars ) {
    820                 os << pair.first << " (" << pair.second << ") ";
    821         } // for
    822         os << std::endl;
    823 }
    824 
    825818} // namespace GenPoly
    826819
  • src/GenPoly/GenPoly.h

    re874605 r93d2219  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Oct  7 15:06:00 2022
    13 // Update Count     : 9
     12// Last Modified On : Mon Oct 24 15:18:00 2022
     13// Update Count     : 11
    1414//
    1515
     
    2222#include "AST/Decl.hpp"           // for TypeDecl::Data
    2323#include "AST/Fwd.hpp"            // for ApplicationExpr, BaseInstType, Func...
     24#include "AST/Type.hpp"           // for TypeInstType::TypeEnvKey
    2425#include "SymTab/Mangler.h"       // for Mangler
    2526#include "SynTree/Declaration.h"  // for TypeDecl::Data, AggregateDecl, Type...
     
    2829namespace GenPoly {
    2930
    30         // TODO Via some tricks this works for ast::TypeDecl::Data as well.
    3131        typedef ErasableScopedMap< std::string, TypeDecl::Data > TyVarMap;
    32         using TypeVarMap = ErasableScopedMap< std::string, ast::TypeDecl::Data >;
     32        using TypeVarMap = ErasableScopedMap< ast::TypeInstType::TypeEnvKey, ast::TypeDecl::Data >;
    3333
    3434        /// Replaces a TypeInstType by its referrent in the environment, if applicable
    3535        Type* replaceTypeInst( Type* type, const TypeSubstitution* env );
     36        const ast::Type * replaceTypeInst( const ast::Type *, const ast::TypeSubstitution * );
    3637
    3738        /// returns polymorphic type if is polymorphic type, NULL otherwise; will look up substitution in env if provided
     
    5354        /// true iff function has dynamic-layout return type under the type variable map generated from its forall-parameters
    5455        ReferenceToType *isDynRet( FunctionType *function );
     56        const ast::BaseInstType *isDynRet( const ast::FunctionType * func );
    5557
    5658        /// A function needs an adapter if it returns a dynamic-layout value or if any of its parameters have dynamic-layout type
     
    112114        /// Prints type variable map
    113115        void printTyVarMap( std::ostream &os, const TyVarMap &tyVarMap );
    114         void printTypeVarMap( std::ostream &os, const TypeVarMap & typeVars );
    115116
    116117        /// Gets the mangled name of this type; alias for SymTab::Mangler::mangleType().
     
    128129        /// Gets the name of the layout function for a given aggregate type, given its declaration
    129130        inline std::string layoutofName( AggregateDecl *decl ) { return std::string( "_layoutof_" ) + decl->get_name(); }
     131        inline std::string layoutofName( ast::AggregateDecl const * decl ) {
     132                return std::string( "_layoutof_" ) + decl->name;
     133        }
    130134
    131135} // namespace GenPoly
  • src/GenPoly/InstantiateGenericNew.cpp

    re874605 r93d2219  
    2626#include "AST/Pass.hpp"                // for Pass, WithGuard, WithShortCi...
    2727#include "AST/TranslationUnit.hpp"     // for TranslationUnit
     28#include "AST/Vector.hpp"              // for vector
    2829#include "CodeGen/OperatorTable.h"     // for isAssignment
    2930#include "Common/ScopedMap.h"          // for ScopedMap
     
    3940// Utilities:
    4041
    41 using type_vector = std::vector< ast::ptr< ast::TypeExpr > >;
     42using type_vector = ast::vector< ast::TypeExpr >;
    4243
    4344/// Abstracts type equality for a list of parameter types.
    4445struct TypeList {
    4546        TypeList() : params() {}
    46         TypeList( std::vector< ast::ptr< ast::Type > > const & params ) :
     47        TypeList( ast::vector< ast::Type > const & params ) :
    4748                params( params ) {}
    48         TypeList( std::vector< ast::ptr< ast::Type > > && params ) :
     49        TypeList( ast::vector< ast::Type > && params ) :
    4950                params( std::move( params ) ) {}
    5051        TypeList( TypeList const & that ) : params( that.params ) {}
    5152        TypeList( TypeList && that ) : params( std::move( that.params ) ) {}
    5253
    53         TypeList( std::vector< ast::ptr< ast::TypeExpr > > const & exprs ) :
     54        TypeList( ast::vector< ast::TypeExpr > const & exprs ) :
    5455                        params() {
    5556                for ( auto expr : exprs ) {
     
    8283        }
    8384
    84         std::vector<ast::ptr<ast::Type>> params;
     85        ast::vector<ast::Type> params;
    8586};
    8687
     
    103104        /// returns null if no such value exists.
    104105        ast::AggregateDecl const * lookup(
    105                         ast::AggregateDecl const * key, type_vector const & params ) const {
     106                        ast::AggregateDecl const * key,
     107                        type_vector const & params ) const {
    106108                // This type repackaging is used for the helpers.
    107109                ast::ptr<ast::AggregateDecl> ptr = key;
     
    150152}
    151153
    152 bool isDtypeStatic( std::vector<ast::ptr<ast::TypeDecl>> const & baseParams ) {
     154bool isDtypeStatic( ast::vector<ast::TypeDecl> const & baseParams ) {
    153155        return std::all_of( baseParams.begin(), baseParams.end(),
    154156                []( ast::TypeDecl const * td ){ return !td->isComplete(); }
     
    161163/// least one parameter type, and dynamic if there is no concrete instantiation.
    162164GenericType makeSubstitutions(
    163                 std::vector<ast::ptr<ast::TypeExpr>> & out,
    164                 std::vector<ast::ptr<ast::TypeDecl>> const & baseParams,
    165                 std::vector<ast::ptr<ast::Expr>> const & params ) {
     165                ast::vector<ast::TypeExpr> & out,
     166                ast::vector<ast::TypeDecl> const & baseParams,
     167                ast::vector<ast::Expr> const & params ) {
    166168        GenericType gt = GenericType::dtypeStatic;
    167169
     
    214216/// Substitutes types of members according to baseParams => typeSubs,
    215217/// returning the result in a new vector.
    216 std::vector<ast::ptr<ast::Decl>> substituteMembers(
    217                 std::vector<ast::ptr<ast::Decl>> const & members,
    218                 std::vector<ast::ptr<ast::TypeDecl>> const & baseParams,
    219                 std::vector<ast::ptr<ast::TypeExpr>> const & typeSubs ) {
    220         std::vector<ast::ptr<ast::Decl>> out;
     218ast::vector<ast::Decl> substituteMembers(
     219                ast::vector<ast::Decl> const & members,
     220                ast::vector<ast::TypeDecl> const & baseParams,
     221                ast::vector<ast::TypeExpr> const & typeSubs ) {
     222        ast::vector<ast::Decl> out;
    221223        ast::TypeSubstitution subs( baseParams, typeSubs );
    222224        for ( ast::ptr<ast::Decl> const & member : members ) {
     
    235237/// modifying them in-place.
    236238void substituteMembersHere(
    237                 std::vector<ast::ptr<ast::Decl>> & members,
    238                 std::vector<ast::ptr<ast::TypeDecl>> const & baseParams,
    239                 std::vector<ast::ptr<ast::TypeExpr>> const & typeSubs ) {
     239                ast::vector<ast::Decl> & members,
     240                ast::vector<ast::TypeDecl> const & baseParams,
     241                ast::vector<ast::TypeExpr> const & typeSubs ) {
    240242        ast::TypeSubstitution subs( baseParams, typeSubs );
    241243        for ( ast::ptr<ast::Decl> & member : members ) {
     
    285287
    286288        ast::Expr const * fixMemberExpr(
    287                 std::vector<ast::ptr<ast::TypeDecl>> const & baseParams,
     289                ast::vector<ast::TypeDecl> const & baseParams,
    288290                ast::MemberExpr const * memberExpr );
    289291
     
    349351
    350352ast::Expr const * FixDtypeStatic::fixMemberExpr(
    351                 std::vector<ast::ptr<ast::TypeDecl>> const & baseParams,
     353                ast::vector<ast::TypeDecl> const & baseParams,
    352354                ast::MemberExpr const * memberExpr ) {
    353355        // Need to cast dtype-static member expressions to their actual type
     
    461463                type_vector const & typeSubs, ast::UnionDecl const * decl );
    462464
    463         void replaceParametersWithConcrete( std::vector<ast::ptr<ast::Expr>> & params );
     465        void replaceParametersWithConcrete( ast::vector<ast::Expr> & params );
    464466        ast::Type const * replaceWithConcrete( ast::Type const * type, bool doClone );
    465467
     
    470472        /// marks it as stripped.
    471473        void stripDtypeParams( ast::AggregateDecl * base,
    472                 std::vector<ast::ptr<ast::TypeDecl>> & baseParams,
    473                 std::vector<ast::ptr<ast::TypeExpr>> const & typeSubs );
     474                ast::vector<ast::TypeDecl> & baseParams,
     475                ast::vector<ast::TypeExpr> const & typeSubs );
    474476};
    475477
     
    511513        // and put substitutions in typeSubs.
    512514        assertf( inst->base, "Base data-type has parameters." );
    513         std::vector<ast::ptr<ast::TypeExpr>> typeSubs;
     515        ast::vector<ast::TypeExpr> typeSubs;
    514516        GenericType gt = makeSubstitutions( typeSubs, inst->base->params, inst->params );
    515517        switch ( gt ) {
     
    570572                ast::AggregateDecl const * aggr =
    571573                        expr->aggregate->result.strict_as<ast::BaseInstType>()->aggr();
    572                 std::vector<ast::ptr<ast::Decl>> const & members = aggr->members;
     574                ast::vector<ast::Decl> const & members = aggr->members;
    573575                auto it = std::find( members.begin(), members.end(), expr->member );
    574576                memberIndex = std::distance( members.begin(), it );
     
    643645
    644646void GenericInstantiator::replaceParametersWithConcrete(
    645                 std::vector<ast::ptr<ast::Expr>> & params ) {
     647                ast::vector<ast::Expr> & params ) {
    646648        for ( ast::ptr<ast::Expr> & param : params ) {
    647649                auto paramType = param.as<ast::TypeExpr>();
     
    673675void GenericInstantiator::stripDtypeParams(
    674676                ast::AggregateDecl * base,
    675                 std::vector<ast::ptr<ast::TypeDecl>> & baseParams,
    676                 std::vector<ast::ptr<ast::TypeExpr>> const & typeSubs ) {
     677                ast::vector<ast::TypeDecl> & baseParams,
     678                ast::vector<ast::TypeExpr> const & typeSubs ) {
    677679        substituteMembersHere( base->members, baseParams, typeSubs );
    678680
  • src/GenPoly/ScrubTyVars.cc

    re874605 r93d2219  
    2020#include "GenPoly/ErasableScopedMap.h"  // for ErasableScopedMap<>::const_it...
    2121#include "ScrubTyVars.h"
    22 #include "SymTab/Mangler.h"             // for mangle, typeMode
     22#include "SymTab/Mangler.h"             // for mangleType
    2323#include "SynTree/Declaration.h"        // for TypeDecl, TypeDecl::Data, Typ...
    2424#include "SynTree/Expression.h"         // for Expression (ptr only), NameExpr
     
    195195        }
    196196
    197         auto typeVar = typeVars->find( type->name );
     197        auto typeVar = typeVars->find( *type );
    198198        if ( typeVar == typeVars->end() ) {
    199199                return type;
     
    227227        if ( dynType ) {
    228228                return new ast::NameExpr( expr->location,
    229                         sizeofName( Mangle::mangle( dynType, Mangle::typeMode() ) ) );
     229                        sizeofName( Mangle::mangleType( dynType ) ) );
    230230        } else {
    231231                return expr;
     
    237237        if ( dynType ) {
    238238                return new ast::NameExpr( expr->location,
    239                         alignofName( Mangle::mangle( dynType, Mangle::typeMode() ) ) );
     239                        alignofName( Mangle::mangleType( dynType ) ) );
    240240        } else {
    241241                return expr;
  • src/Parser/ParseNode.h

    re874605 r93d2219  
    1010// Created On       : Sat May 16 13:28:16 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Oct 18 14:15:37 2022
    13 // Update Count     : 936
     12// Last Modified On : Tue Oct 18 16:22:15 2022
     13// Update Count     : 937
    1414//
    1515
     
    468468                cur = dynamic_cast< const NodeType * >( temp ); // should not return nullptr
    469469                if ( ! cur && temp ) {                                                  // non-homogeneous nodes ?
    470                         SemanticError( cur->location, "internal error, non-homogeneous nodes founds in buildList processing." );
     470                        SemanticError( temp->location, "internal error, non-homogeneous nodes founds in buildList processing." );
    471471                } // if
    472472        } // while
  • src/ResolvExpr/SatisfyAssertions.cpp

    re874605 r93d2219  
    268268                ast::ptr< ast::Type > resType = cand.expr->result;
    269269                cand.env.apply( resType );
    270                 return Mangle::mangle( resType, Mangle::typeMode() );
     270                return Mangle::mangleType( resType );
    271271        }
    272272
  • src/SymTab/Mangler.cc

    re874605 r93d2219  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 21:40:29 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Jan 11 21:56:06 2021
    13 // Update Count     : 74
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Oct 21 16:18:00 2022
     13// Update Count     : 75
    1414//
    1515#include "Mangler.h"
     
    418418                        void postvisit( const ast::QualifiedType * qualType );
    419419
    420                         std::string get_mangleName() { return mangleName; }
     420                        /// The result is the current constructed mangled name.
     421                        std::string result() const { return mangleName; }
    421422                  private:
    422423                        std::string mangleName;         ///< Mangled name being constructed
     
    444445        } // namespace
    445446
    446 
    447447        std::string mangle( const ast::Node * decl, Mangle::Mode mode ) {
    448                 ast::Pass<Mangler_new> mangler( mode );
    449                 maybeAccept( decl, mangler );
    450                 return mangler.core.get_mangleName();
     448                return ast::Pass<Mangler_new>::read( decl, mode );
    451449        }
    452450
     
    689687                                        } // for
    690688                                        for ( auto & assert : ptype->assertions ) {
    691                                                 ast::Pass<Mangler_new> sub_mangler(
    692                                                         mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums );
    693                                                 assert->var->accept( sub_mangler );
    694                                                 assertionNames.push_back( sub_mangler.core.get_mangleName() );
     689                                                assertionNames.push_back( ast::Pass<Mangler_new>::read(
     690                                                        assert->var.get(),
     691                                                        mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums ) );
    695692                                                acount++;
    696693                                        } // for
  • src/SymTab/Mangler.h

    re874605 r93d2219  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 21:44:03 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:45:30 2017
    13 // Update Count     : 15
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thu Oct 27 11:58:00 2022
     13// Update Count     : 16
    1414//
    1515
     
    2222
    2323#include "AST/Bitfield.hpp"
    24 #include "AST/Fwd.hpp"
    2524#include "SynTree/SynTree.h"  // for Types
    2625#include "SynTree/Visitor.h"  // for Visitor, maybeAccept
     
    3332// * Currently name compression is not implemented.
    3433
     34namespace ast {
     35        class Node;
     36}
    3537namespace ResolvExpr {
    3638        class TypeEnvironment;
     
    101103        using Mode = bitfield<mangle_flags>;
    102104
    103         static inline Mode typeMode() { return NoOverrideable | Type; }
     105        /// Mangle declaration name.
     106        std::string mangle( const ast::Node * decl, Mode mode = {} );
    104107
    105         /// Mangle declaration name
    106         std::string mangle( const ast::Node * decl, Mode mode = {} );
     108        /// Most common mangle configuration for types.
     109        static inline std::string mangleType( const ast::Node * type ) {
     110                return mangle( type, { NoOverrideable | Type } );
     111        }
    107112
    108113        namespace Encoding {
  • src/SynTree/AddressExpr.cc

    re874605 r93d2219  
    5050                                set_result( addrType( refType->base ) );
    5151                        } else {
     52                                if(!arg->result->location.isSet()) arg->result->location = arg->location;
    5253                                SemanticError( arg->result, "Attempt to take address of non-lvalue expression: " );
    5354                        } // if
  • src/Virtual/ExpandCasts.cc

    re874605 r93d2219  
    295295        // returns the previous declaration for error messages.
    296296        ast::ObjectDecl const * insert( ast::ObjectDecl const * typeIdDecl ) {
    297                 std::string const & mangledName =
    298                                 Mangle::mangle( typeIdDecl->type, Mangle::typeMode() );
     297                std::string mangledName = Mangle::mangleType( typeIdDecl->type );
    299298                ast::ObjectDecl const *& value = instances[ mangledName ];
    300299                if ( value ) {
     
    310309
    311310        ast::ObjectDecl const * lookup( ast::Type const * typeIdType ) {
    312                 std::string const & mangledName =
    313                                 Mangle::mangle( typeIdType, Mangle::typeMode() );
     311                std::string mangledName = Mangle::mangleType( typeIdType );
    314312                auto const it = instances.find( mangledName );
    315313                return ( instances.end() == it ) ? nullptr : it->second;
  • tests/array-container/array-basic.cfa

    re874605 r93d2219  
    7878}
    7979
    80 forall( A & | ar(A, float) )
     80forall( [N], A & | ar(A, float, N) )
    8181float total1d_hi( A & a ) {
    8282    float total = 0.0f;
    83     for (i; a`len)
     83    for (i; N)
    8484        total += a[i];
    8585    return total;
  • tests/collections/atomic_mpsc.cfa

    re874605 r93d2219  
    11#include <fstream.hfa>
    2 #include <queueLockFree.hfa>
     2#include <containers/lockfree.hfa>
    33#include <thread.hfa>
    44
  • tests/configs/parsebools.cfa

    re874605 r93d2219  
    1515//
    1616
    17 #include <parseargs.hfa>
    1817#include <fstream.hfa>
    1918
    2019#include "../meta/fork+exec.hfa"
     20
     21// last as a work around to a parse bug
     22#include <parseargs.hfa>
    2123
    2224int main(int argc, char * argv[]) {
     
    3032        bool sf = true;
    3133
    32         cfa_option options[] = {
    33                 {'e', "yesno",     "test yes/no",     YN, parse_yesno},
    34                 {'y', "YN",        "test yes/no",     Yn, parse_yesno},
    35                 {'n', "yn",        "test yes/no",     yn, parse_yesno},
    36                 {'t', "truefalse", "test true/false", tf, parse_truefalse},
    37                 {'s', "settrue",   "test set true",   st, parse_settrue},
    38                 {'u', "setfalse",  "test set false",  sf, parse_setfalse},
    39         };
    40         int options_cnt = sizeof(options) / sizeof(cfa_option);
     34        array( cfa_option, 6 ) options;
     35        options[0] = (cfa_option){'e', "yesno",     "test yes/no",     YN, parse_yesno};
     36        options[1] = (cfa_option){'y', "YN",        "test yes/no",     Yn, parse_yesno};
     37        options[2] = (cfa_option){'n', "yn",        "test yes/no",     yn, parse_yesno};
     38        options[3] = (cfa_option){'t', "truefalse", "test true/false", tf, parse_truefalse};
     39        options[4] = (cfa_option){'s', "settrue",   "test set true",   st, parse_settrue};
     40        options[5] = (cfa_option){'u', "setfalse",  "test set false",  sf, parse_setfalse};
    4141
    4242        char **left;
    43         parse_args( options, options_cnt, "[OPTIONS]...\ntesting bool parameters", left);
     43        parse_args( options, "[OPTIONS]...\ntesting bool parameters", left);
    4444
    4545        sout | "yes/no     :" | YN;
  • tests/configs/parsenums.cfa

    re874605 r93d2219  
    1515//
    1616
     17#include <fstream.hfa>
     18
     19#include "../meta/fork+exec.hfa"
     20
     21// last as workaround to parser bug
    1722#include <parseargs.hfa>
    18 #include <fstream.hfa>
    19 
    20 #include "../meta/fork+exec.hfa"
    2123
    2224#if __SIZEOF_LONG__ == 4
     
    4244
    4345
    44         cfa_option options[] = {
    45                 { 'i', "int",              "test int",                i   },
    46                 { 'u', "unsigned",         "test unsigned",           u   },
    47                 { 'l', "unsignedlong",     "test unsigned long",      ul  },
    48                 { 'L', "unsignedlonglong", "test unsigned long long", ull },
    49                 { 'd', "double",           "test double",             d   },
    50         };
    51         int options_cnt = sizeof(options) / sizeof(cfa_option);
     46        array( cfa_option, 5 ) options;
     47        options[0] = (cfa_option){ 'i', "int",              "test int",                i   };
     48        options[1] = (cfa_option){ 'u', "unsigned",         "test unsigned",           u   };
     49        options[2] = (cfa_option){ 'l', "unsignedlong",     "test unsigned long",      ul  };
     50        options[3] = (cfa_option){ 'L', "unsignedlonglong", "test unsigned long long", ull };
     51        options[4] = (cfa_option){ 'd', "double",           "test double",             d   };
    5252
    5353        char **left;
    54         parse_args( options, options_cnt, "[OPTIONS]...\ntesting bool parameters", left);
     54        parse_args( options, "[OPTIONS]...\ntesting bool parameters", left);
    5555
    5656        sout | "int                :" | i;
  • tests/configs/usage.cfa

    re874605 r93d2219  
    1515//
    1616
     17#include <fstream.hfa>
     18#include "../meta/fork+exec.hfa"
    1719#include <parseargs.hfa>
    18 #include <fstream.hfa>
    1920
    20 #include "../meta/fork+exec.hfa"
    2121
    2222int main() {
     
    2525        sout | "No args, no errors";
    2626        if(pid_t child = strict_fork(); child == 0) {
    27                 cfa_option opts[0];
    28                 print_args_usage(1, fake_argv, opts, 0, "Test usage", false);
     27                array( cfa_option, 0 ) opts;
     28                print_args_usage(1, fake_argv, opts, "Test usage", false);
    2929        }
    3030        else {
     
    3535        sout | "No args, with errors";
    3636        if(pid_t child = strict_fork(); child == 0) {
    37                 cfa_option opts[0];
    38                 print_args_usage(1, fake_argv, opts, 0, "Test usage", true);
     37                array( cfa_option, 0 ) opts;
     38                print_args_usage(1, fake_argv, opts, "Test usage", true);
    3939        }
    4040        else {
     
    4646        if(pid_t child = strict_fork(); child == 0) {
    4747                int a, b, c;
    48                 cfa_option opts[] = {
    49                         {'a', "", "First arg", a },
    50                         {'b', "", "Second arg", b },
    51                         {'c', "", "Third arg", c },
    52                 };
    53                 print_args_usage(1, fake_argv, opts, 3, "Test usage", false);
     48                array( cfa_option, 3 ) opts;
     49                opts[0] = (cfa_option){'a', "", "First arg", a };
     50                opts[1] = (cfa_option){'b', "", "Second arg", b };
     51                opts[2] = (cfa_option){'c', "", "Third arg", c };
     52                print_args_usage(1, fake_argv, opts, "Test usage", false);
    5453        }
    5554        else {
     
    6160        if(pid_t child = strict_fork(); child == 0) {
    6261                int a, b, c;
    63                 cfa_option opts[] = {
    64                         {'\0', "AA", "First arg", a },
    65                         {'\0', "BB", "Second arg", b },
    66                         {'\0', "CC", "Third arg", c },
    67                 };
    68                 print_args_usage(1, fake_argv, opts, 3, "Test usage", false);
     62                array( cfa_option, 3 ) opts;
     63                opts[0] = (cfa_option){'\0', "AA", "First arg", a };
     64                opts[1] = (cfa_option){'\0', "BB", "Second arg", b };
     65                opts[2] = (cfa_option){'\0', "CC", "Third arg", c };
     66                print_args_usage(1, fake_argv, opts, "Test usage", false);
    6967        }
    7068        else {
     
    7674        if(pid_t child = strict_fork(); child == 0) {
    7775                int a, b, c;
    78                 cfa_option opts[] = {
    79                         {'a', "", "First arg", a },
    80                         {'b', "BBBB", "Second arg", b },
    81                         {'\0', "CC", "Third arg", c },
    82                 };
    83                 print_args_usage(1, fake_argv, opts, 3, "Test usage", false);
     76                array( cfa_option, 3 ) opts;
     77                opts[0] = (cfa_option){'a', "", "First arg", a };
     78                opts[1] = (cfa_option){'b', "BBBB", "Second arg", b };
     79                opts[2] = (cfa_option){'\0', "CC", "Third arg", c };
     80                print_args_usage(1, fake_argv, opts, "Test usage", false);
    8481        }
    8582        else {
     
    9188        if(pid_t child = strict_fork(); child == 0) {
    9289                int a, b, c;
    93                 cfa_option opts[] = {
    94                         {'a', "", "First arg", a },
    95                         {'b', "BBBB", "", b },
    96                         {'\0', "CC", "Third arg", c },
    97                 };
    98                 print_args_usage(1, fake_argv, opts, 3, "Test usage", false);
     90                array( cfa_option, 3 ) opts;
     91                opts[0] = (cfa_option){'a', "", "First arg", a };
     92                opts[1] = (cfa_option){'b', "BBBB", "", b };
     93                opts[2] = (cfa_option){'\0', "CC", "Third arg", c };
     94                print_args_usage(1, fake_argv, opts, "Test usage", false);
    9995        }
    10096        else {
     
    106102        if(pid_t child = strict_fork(); child == 0) {
    107103                int a, b, c;
    108                 cfa_option opts[] = {
    109                         {'a', "", "First arg\nThe description has multiple lines,\n...for some reason", a },
    110                         {'b', "BBBB", "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890", b },
    111                         {'\0', "CC", "Third arg", c },
    112                 };
    113                 print_args_usage(1, fake_argv, opts, 3, "Test usage", false);
     104                array( cfa_option, 3 ) opts;
     105                opts[0] = (cfa_option){'a', "", "First arg\nThe description has multiple lines,\n...for some reason", a };
     106                opts[1] = (cfa_option){'b', "BBBB", "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890", b };
     107                opts[2] = (cfa_option){'\0', "CC", "Third arg", c };
     108                print_args_usage(1, fake_argv, opts, "Test usage", false);
    114109        }
    115110        else {
  • tests/device/cpu.cfa

    re874605 r93d2219  
    117117unsigned find_idx() {
    118118        int idxs = count_cache_indexes();
     119        if( 0 == idxs ) return 0;
    119120
    120121        unsigned found_level = 0;
     
    179180        unsigned idx = find_idx();
    180181        // For all procs check mapping is consistent
    181         for(cpu_me; cpu_info.hthrd_count) {
     182        if( idx > 0 ) for(cpu_me; cpu_info.hthrd_count) {
    182183                char buf_me[32];
    183184                size_t len_me = read_cpuidxinfo_into(cpu_me, idx, "shared_cpu_list", buf_me, 32);
Note: See TracChangeset for help on using the changeset viewer.