ck_str_hash_lookup:
  146|  5.00k|const void *ck_str_hash_lookup(const char *key, ck_hash_table_t *table) {
  147|  5.00k|    size_t keylen = strlen(key);
  148|  5.00k|    return ck_str_n_hash_lookup(key, keylen, table);
  149|  5.00k|}
ck_str_n_hash_lookup:
  152|  5.00k|{
  153|  5.00k|	if (table->count == 0)
  ------------------
  |  Branch (153:6): [True: 884, False: 4.12k]
  ------------------
  154|    884|		return NULL;
  155|       |    	
  156|  4.12k|	if (keylen == 0)
  ------------------
  |  Branch (156:6): [True: 338, False: 3.78k]
  ------------------
  157|    338|		return NULL;
  158|       |	
  159|  3.78k|    uint64_t hash_key = ck_hash_str(key, keylen);
  160|  3.78k|	hash_key %= table->capacity;
  161|  3.78k|    uint64_t end = hash_key;
  162|  4.20k|    do {
  163|  4.20k|        char *this_key = &table->keys[table->entries[hash_key].key_offset];
  164|  4.20k|        size_t this_keylen = table->entries[hash_key].key_length;
  165|  4.20k|        if (this_keylen == 0)
  ------------------
  |  Branch (165:13): [True: 1.62k, False: 2.57k]
  ------------------
  166|  1.62k|            return NULL;
  167|  2.57k|        if (this_keylen == keylen && memcmp(this_key, key, keylen) == 0) {
  ------------------
  |  Branch (167:13): [True: 2.37k, False: 195]
  |  Branch (167:38): [True: 2.15k, False: 220]
  ------------------
  168|  2.15k|			return table->entries[hash_key].value;
  169|  2.15k|		}
  170|    415|		hash_key++;
  171|    415|		hash_key %= table->capacity;
  172|    415|    } while (hash_key != end);
  ------------------
  |  Branch (172:14): [True: 415, False: 0]
  ------------------
  173|      0|	return NULL;
  174|  3.78k|}
ck_str_hash_insert:
  177|  9.44k|{
  178|  9.44k|    size_t keylen = strlen(key);
  179|  9.44k|    return ck_str_n_hash_insert(key, keylen, value, table);
  180|  9.44k|}
ck_str_n_hash_insert:
  210|  9.44k|{    
  211|  9.44k|	if (table->capacity == 0)
  ------------------
  |  Branch (211:6): [True: 0, False: 9.44k]
  ------------------
  212|      0|		return 0;
  213|       |    	
  214|  9.44k|	if (keylen == 0)
  ------------------
  |  Branch (214:6): [True: 4.35k, False: 5.09k]
  ------------------
  215|  4.35k|		return 0;
  216|       |    
  217|  5.09k|    if (table->count >= 0.75 * table->capacity) {
  ------------------
  |  Branch (217:9): [True: 0, False: 5.09k]
  ------------------
  218|      0|        if (ck_hash_table_grow(table) == -1) {
  ------------------
  |  Branch (218:13): [True: 0, False: 0]
  ------------------
  219|      0|            return 0;
  220|      0|        }
  221|      0|    }
  222|       |	
  223|  5.09k|    uint64_t hash_key = ck_hash_str(key, keylen);
  224|  5.09k|	hash_key %= table->capacity;
  225|  5.09k|    uint64_t end = hash_key;
  226|  5.88k|    do {
  227|  5.88k|        ck_hash_entry_t *entry = &table->entries[hash_key];
  228|  5.88k|        char *this_key = &table->keys[entry->key_offset];
  229|  5.88k|        if (entry->key_length == 0) {
  ------------------
  |  Branch (229:13): [True: 1.13k, False: 4.75k]
  ------------------
  230|  1.13k|            table->count++;
  231|  1.13k|            while (table->keys_used + keylen > table->keys_capacity) {
  ------------------
  |  Branch (231:20): [True: 0, False: 1.13k]
  ------------------
  232|      0|                table->keys_capacity *= 2;
  233|      0|                table->keys = realloc(table->keys, table->keys_capacity);
  234|      0|            }
  235|  1.13k|            memcpy(table->keys + table->keys_used, key, keylen);
  236|  1.13k|            entry->key_offset = table->keys_used;
  237|  1.13k|            entry->key_length = keylen;
  238|  1.13k|            table->keys_used += keylen;
  239|  1.13k|            entry->value = value;
  240|  1.13k|            return 1;
  241|  4.75k|        } else if (entry->key_length == keylen &&
  ------------------
  |  Branch (241:20): [True: 4.29k, False: 455]
  ------------------
  242|  4.29k|                   memcmp(this_key, key, keylen) == 0) {
  ------------------
  |  Branch (242:20): [True: 3.95k, False: 338]
  ------------------
  243|  3.95k|			table->entries[hash_key].value = value;
  244|  3.95k|			return 1;
  245|  3.95k|		}
  246|    793|		hash_key++;
  247|    793|		hash_key %= table->capacity;
  248|    793|    } while (hash_key != end);
  ------------------
  |  Branch (248:14): [True: 793, False: 0]
  ------------------
  249|      0|	return 0;
  250|  5.09k|}
ck_hash_table_init:
  253|  2.81k|{
  254|  2.81k|	ck_hash_table_t *table;
  255|  2.81k|	if ((table = malloc(sizeof(ck_hash_table_t))) == NULL)
  ------------------
  |  Branch (255:6): [True: 0, False: 2.81k]
  ------------------
  256|      0|		return NULL;
  257|       |    
  258|  2.81k|    if ((table->keys = malloc(num_entries * mean_key_length)) == NULL) {
  ------------------
  |  Branch (258:9): [True: 0, False: 2.81k]
  ------------------
  259|      0|        free(table);
  260|      0|        return NULL;
  261|      0|    }
  262|  2.81k|    table->keys_capacity = num_entries * mean_key_length;
  263|       |    
  264|  2.81k|    num_entries *= 2;
  265|       |    
  266|  2.81k|    if ((table->entries = malloc(num_entries * sizeof(ck_hash_entry_t))) == NULL) {
  ------------------
  |  Branch (266:9): [True: 0, False: 2.81k]
  ------------------
  267|      0|        free(table->keys);
  268|      0|        free(table);
  269|      0|        return NULL;
  270|      0|    }
  271|  2.81k|	table->capacity = num_entries;
  272|  2.81k|    ck_hash_table_wipe(table);
  273|  2.81k|	return table;
  274|  2.81k|}
ck_hash_table_free:
  276|  2.81k|void ck_hash_table_free(ck_hash_table_t *table) {
  277|  2.81k|    free(table->entries);
  278|  2.81k|    if (table->keys)
  ------------------
  |  Branch (278:9): [True: 2.81k, False: 0]
  ------------------
  279|  2.81k|        free(table->keys);
  280|  2.81k|    free(table);
  281|  2.81k|}
ck_hash_table_wipe:
  283|  2.81k|void ck_hash_table_wipe(ck_hash_table_t *table) {
  284|  2.81k|    table->keys_used = 0;
  285|  2.81k|    table->count = 0;
  286|  2.81k|    memset(table->entries, 0, table->capacity * sizeof(ck_hash_entry_t));
  287|  2.81k|}
CKHashTable.c:ck_hash_str:
  121|  8.88k|{
  122|  8.88k|    uint64_t hash;
  123|  8.88k|    unsigned char k[16] = { 0 };
  124|  8.88k|    siphash((unsigned char *)&hash, (const unsigned char *)str, keylen, k);
  125|  8.88k|    return hash;
  126|  8.88k|}
CKHashTable.c:siphash:
   57|  8.88k|{
   58|       |    /* "somepseudorandomlygeneratedbytes" */
   59|  8.88k|    u64 v0 = 0x736f6d6570736575ULL;
   60|  8.88k|    u64 v1 = 0x646f72616e646f6dULL;
   61|  8.88k|    u64 v2 = 0x6c7967656e657261ULL;
   62|  8.88k|    u64 v3 = 0x7465646279746573ULL;
   63|  8.88k|    u64 b;
   64|  8.88k|    u64 k0 = U8TO64_LE( k );
  ------------------
  |  |   37|  8.88k|#define U8TO64_LE(p) \
  |  |   38|  8.88k|(((u64)((p)[0])      ) | \
  |  |   39|  8.88k|((u64)((p)[1]) <<  8) | \
  |  |   40|  8.88k|((u64)((p)[2]) << 16) | \
  |  |   41|  8.88k|((u64)((p)[3]) << 24) | \
  |  |   42|  8.88k|((u64)((p)[4]) << 32) | \
  |  |   43|  8.88k|((u64)((p)[5]) << 40) | \
  |  |   44|  8.88k|((u64)((p)[6]) << 48) | \
  |  |   45|  8.88k|((u64)((p)[7]) << 56))
  ------------------
   65|  8.88k|    u64 k1 = U8TO64_LE( k + 8 );
  ------------------
  |  |   37|  8.88k|#define U8TO64_LE(p) \
  |  |   38|  8.88k|(((u64)((p)[0])      ) | \
  |  |   39|  8.88k|((u64)((p)[1]) <<  8) | \
  |  |   40|  8.88k|((u64)((p)[2]) << 16) | \
  |  |   41|  8.88k|((u64)((p)[3]) << 24) | \
  |  |   42|  8.88k|((u64)((p)[4]) << 32) | \
  |  |   43|  8.88k|((u64)((p)[5]) << 40) | \
  |  |   44|  8.88k|((u64)((p)[6]) << 48) | \
  |  |   45|  8.88k|((u64)((p)[7]) << 56))
  ------------------
   66|  8.88k|    u64 m;
   67|  8.88k|    const u8 *end = in + inlen - ( inlen % sizeof( u64 ) );
   68|  8.88k|    const int left = inlen & 7;
   69|  8.88k|    b = ( ( u64 )inlen ) << 56;
   70|  8.88k|    v3 ^= k1;
   71|  8.88k|    v2 ^= k0;
   72|  8.88k|    v1 ^= k1;
   73|  8.88k|    v0 ^= k0;
   74|       |    
   75|  16.5k|    for ( ; in != end; in += 8 )
  ------------------
  |  Branch (75:13): [True: 7.63k, False: 8.88k]
  ------------------
   76|  7.63k|    {
   77|  7.63k|        m = U8TO64_LE( in );
  ------------------
  |  |   37|  7.63k|#define U8TO64_LE(p) \
  |  |   38|  7.63k|(((u64)((p)[0])      ) | \
  |  |   39|  7.63k|((u64)((p)[1]) <<  8) | \
  |  |   40|  7.63k|((u64)((p)[2]) << 16) | \
  |  |   41|  7.63k|((u64)((p)[3]) << 24) | \
  |  |   42|  7.63k|((u64)((p)[4]) << 32) | \
  |  |   43|  7.63k|((u64)((p)[5]) << 40) | \
  |  |   44|  7.63k|((u64)((p)[6]) << 48) | \
  |  |   45|  7.63k|((u64)((p)[7]) << 56))
  ------------------
   78|       |        
   79|  7.63k|        v3 ^= m;
   80|       |        
   81|  7.63k|        SIPROUND;
  ------------------
  |  |   47|  7.63k|#define SIPROUND            \
  |  |   48|  7.63k|do {              \
  |  |   49|  7.63k|v0 += v1; v1=ROTL(v1,13); v1 ^= v0; v0=ROTL(v0,32); \
  |  |  ------------------
  |  |  |  |   27|  7.63k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |               v0 += v1; v1=ROTL(v1,13); v1 ^= v0; v0=ROTL(v0,32); \
  |  |  ------------------
  |  |  |  |   27|  7.63k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |   50|  7.63k|v2 += v3; v3=ROTL(v3,16); v3 ^= v2;     \
  |  |  ------------------
  |  |  |  |   27|  7.63k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |   51|  7.63k|v0 += v3; v3=ROTL(v3,21); v3 ^= v0;     \
  |  |  ------------------
  |  |  |  |   27|  7.63k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |   52|  7.63k|v2 += v1; v1=ROTL(v1,17); v1 ^= v2; v2=ROTL(v2,32); \
  |  |  ------------------
  |  |  |  |   27|  7.63k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |               v2 += v1; v1=ROTL(v1,17); v1 ^= v2; v2=ROTL(v2,32); \
  |  |  ------------------
  |  |  |  |   27|  7.63k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |   53|  7.63k|} while(0)
  |  |  ------------------
  |  |  |  Branch (53:9): [Folded, False: 7.63k]
  |  |  ------------------
  ------------------
   82|       |        
   83|  7.63k|        v0 ^= m;
   84|  7.63k|    }
   85|       |    
   86|  8.88k|    switch( left )
  ------------------
  |  Branch (86:13): [True: 8.88k, False: 0]
  ------------------
   87|  8.88k|    {
   88|    306|        case 7: b |= ( ( u64 )in[ 6] )  << 48;
  ------------------
  |  Branch (88:9): [True: 306, False: 8.57k]
  ------------------
   89|       |            
   90|  1.60k|        case 6: b |= ( ( u64 )in[ 5] )  << 40;
  ------------------
  |  Branch (90:9): [True: 1.30k, False: 7.58k]
  ------------------
   91|       |            
   92|  2.01k|        case 5: b |= ( ( u64 )in[ 4] )  << 32;
  ------------------
  |  Branch (92:9): [True: 404, False: 8.47k]
  ------------------
   93|       |            
   94|  3.38k|        case 4: b |= ( ( u64 )in[ 3] )  << 24;
  ------------------
  |  Branch (94:9): [True: 1.37k, False: 7.50k]
  ------------------
   95|       |            
   96|  3.80k|        case 3: b |= ( ( u64 )in[ 2] )  << 16;
  ------------------
  |  Branch (96:9): [True: 420, False: 8.46k]
  ------------------
   97|       |            
   98|  4.65k|        case 2: b |= ( ( u64 )in[ 1] )  <<  8;
  ------------------
  |  Branch (98:9): [True: 843, False: 8.03k]
  ------------------
   99|       |            
  100|  5.66k|        case 1: b |= ( ( u64 )in[ 0] ); break;
  ------------------
  |  Branch (100:9): [True: 1.01k, False: 7.86k]
  ------------------
  101|       |            
  102|  3.21k|        case 0: break;
  ------------------
  |  Branch (102:9): [True: 3.21k, False: 5.66k]
  ------------------
  103|  8.88k|    }
  104|       |
  105|  8.88k|    v3 ^= b;
  106|       |    
  107|  8.88k|    SIPROUND;
  ------------------
  |  |   47|  8.88k|#define SIPROUND            \
  |  |   48|  8.88k|do {              \
  |  |   49|  8.88k|v0 += v1; v1=ROTL(v1,13); v1 ^= v0; v0=ROTL(v0,32); \
  |  |  ------------------
  |  |  |  |   27|  8.88k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |               v0 += v1; v1=ROTL(v1,13); v1 ^= v0; v0=ROTL(v0,32); \
  |  |  ------------------
  |  |  |  |   27|  8.88k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |   50|  8.88k|v2 += v3; v3=ROTL(v3,16); v3 ^= v2;     \
  |  |  ------------------
  |  |  |  |   27|  8.88k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |   51|  8.88k|v0 += v3; v3=ROTL(v3,21); v3 ^= v0;     \
  |  |  ------------------
  |  |  |  |   27|  8.88k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |   52|  8.88k|v2 += v1; v1=ROTL(v1,17); v1 ^= v2; v2=ROTL(v2,32); \
  |  |  ------------------
  |  |  |  |   27|  8.88k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |               v2 += v1; v1=ROTL(v1,17); v1 ^= v2; v2=ROTL(v2,32); \
  |  |  ------------------
  |  |  |  |   27|  8.88k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |   53|  8.88k|} while(0)
  |  |  ------------------
  |  |  |  Branch (53:9): [Folded, False: 8.88k]
  |  |  ------------------
  ------------------
  108|       |    
  109|  8.88k|    v0 ^= b;
  110|  8.88k|    v2 ^= 0xff;
  111|       |    
  112|  8.88k|    SIPROUND;
  ------------------
  |  |   47|  8.88k|#define SIPROUND            \
  |  |   48|  8.88k|do {              \
  |  |   49|  8.88k|v0 += v1; v1=ROTL(v1,13); v1 ^= v0; v0=ROTL(v0,32); \
  |  |  ------------------
  |  |  |  |   27|  8.88k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |               v0 += v1; v1=ROTL(v1,13); v1 ^= v0; v0=ROTL(v0,32); \
  |  |  ------------------
  |  |  |  |   27|  8.88k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |   50|  8.88k|v2 += v3; v3=ROTL(v3,16); v3 ^= v2;     \
  |  |  ------------------
  |  |  |  |   27|  8.88k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |   51|  8.88k|v0 += v3; v3=ROTL(v3,21); v3 ^= v0;     \
  |  |  ------------------
  |  |  |  |   27|  8.88k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |   52|  8.88k|v2 += v1; v1=ROTL(v1,17); v1 ^= v2; v2=ROTL(v2,32); \
  |  |  ------------------
  |  |  |  |   27|  8.88k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |               v2 += v1; v1=ROTL(v1,17); v1 ^= v2; v2=ROTL(v2,32); \
  |  |  ------------------
  |  |  |  |   27|  8.88k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |   53|  8.88k|} while(0)
  |  |  ------------------
  |  |  |  Branch (53:9): [Folded, False: 8.88k]
  |  |  ------------------
  ------------------
  113|  8.88k|    SIPROUND;
  ------------------
  |  |   47|  8.88k|#define SIPROUND            \
  |  |   48|  8.88k|do {              \
  |  |   49|  8.88k|v0 += v1; v1=ROTL(v1,13); v1 ^= v0; v0=ROTL(v0,32); \
  |  |  ------------------
  |  |  |  |   27|  8.88k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |               v0 += v1; v1=ROTL(v1,13); v1 ^= v0; v0=ROTL(v0,32); \
  |  |  ------------------
  |  |  |  |   27|  8.88k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |   50|  8.88k|v2 += v3; v3=ROTL(v3,16); v3 ^= v2;     \
  |  |  ------------------
  |  |  |  |   27|  8.88k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |   51|  8.88k|v0 += v3; v3=ROTL(v3,21); v3 ^= v0;     \
  |  |  ------------------
  |  |  |  |   27|  8.88k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |   52|  8.88k|v2 += v1; v1=ROTL(v1,17); v1 ^= v2; v2=ROTL(v2,32); \
  |  |  ------------------
  |  |  |  |   27|  8.88k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |               v2 += v1; v1=ROTL(v1,17); v1 ^= v2; v2=ROTL(v2,32); \
  |  |  ------------------
  |  |  |  |   27|  8.88k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |   53|  8.88k|} while(0)
  |  |  ------------------
  |  |  |  Branch (53:9): [Folded, False: 8.88k]
  |  |  ------------------
  ------------------
  114|       |    
  115|  8.88k|    b = v0 ^ v1 ^ v2  ^ v3;
  116|  8.88k|    U64TO8_LE( out, b );
  ------------------
  |  |   33|  8.88k|#define U64TO8_LE(p, v)         \
  |  |  ------------------
  |  |  |  |   29|  8.88k|#define U32TO8_LE(p, v)         \
  |  |  |  |   30|  8.88k|(p)[0] = (u8)((v)      ); (p)[1] = (u8)((v) >>  8); \
  |  |  |  |   31|  8.88k|(p)[2] = (u8)((v) >> 16); (p)[3] = (u8)((v) >> 24);
  |  |  ------------------
  |  |   34|  8.88k|U32TO8_LE((p),     (u32)((v)      ));   \
  |  |  ------------------
  |  |  |  |   29|  8.88k|#define U32TO8_LE(p, v)         \
  |  |  |  |   30|  8.88k|(p)[0] = (u8)((v)      ); (p)[1] = (u8)((v) >>  8); \
  |  |  |  |   31|  8.88k|(p)[2] = (u8)((v) >> 16); (p)[3] = (u8)((v) >> 24);
  |  |  ------------------
  |  |   35|  8.88k|U32TO8_LE((p) + 4, (u32)((v) >> 32));
  ------------------
  117|  8.88k|    return 0;
  118|  8.88k|}

fuzzer_parser_init:
   33|  2.81k|readstat_parser_t *fuzzer_parser_init(const uint8_t *Data, size_t Size) {
   34|  2.81k|    readstat_parser_t *parser = readstat_parser_init();
   35|  2.81k|    readstat_set_open_handler(parser, rt_open_handler);
   36|  2.81k|    readstat_set_close_handler(parser, rt_close_handler);
   37|  2.81k|    readstat_set_seek_handler(parser, rt_seek_handler);
   38|  2.81k|    readstat_set_read_handler(parser, rt_read_handler);
   39|  2.81k|    readstat_set_update_handler(parser, rt_update_handler);
   40|       |
   41|  2.81k|    readstat_set_metadata_handler(parser, &handle_metadata);
   42|  2.81k|    readstat_set_note_handler(parser, &handle_note);
   43|  2.81k|    readstat_set_variable_handler(parser, &handle_variable);
   44|  2.81k|    readstat_set_fweight_handler(parser, &handle_fweight);
   45|  2.81k|    readstat_set_value_handler(parser, &handle_value);
   46|  2.81k|    readstat_set_value_label_handler(parser, &handle_value_label);
   47|       |
   48|  2.81k|    return parser;
   49|  2.81k|}
fuzz_format.c:handle_metadata:
    8|  1.15k|static int handle_metadata(readstat_metadata_t *metadata, void *ctx) {
    9|  1.15k|    return READSTAT_HANDLER_OK;
  ------------------
  |  |   22|  1.15k|#define READSTAT_HANDLER_OK             0
  ------------------
   10|  1.15k|}
fuzz_format.c:handle_note:
   12|  1.51k|static int handle_note(int index, const char *note, void *ctx) {
   13|  1.51k|    return READSTAT_HANDLER_OK;
  ------------------
  |  |   22|  1.51k|#define READSTAT_HANDLER_OK             0
  ------------------
   14|  1.51k|}
fuzz_format.c:handle_variable:
   21|  1.66k|                           const char *val_labels, void *ctx) {
   22|  1.66k|    return READSTAT_HANDLER_OK;
  ------------------
  |  |   22|  1.66k|#define READSTAT_HANDLER_OK             0
  ------------------
   23|  1.66k|}
fuzz_format.c:handle_fweight:
   16|      3|static int handle_fweight(readstat_variable_t *variable, void *ctx) {
   17|      3|    return READSTAT_HANDLER_OK;
  ------------------
  |  |   22|      3|#define READSTAT_HANDLER_OK             0
  ------------------
   18|      3|}
fuzz_format.c:handle_value:
   25|  14.3k|static int handle_value(int obs_index, readstat_variable_t *variable, readstat_value_t value, void *ctx) {
   26|  14.3k|    return READSTAT_HANDLER_OK;
  ------------------
  |  |   22|  14.3k|#define READSTAT_HANDLER_OK             0
  ------------------
   27|  14.3k|}
fuzz_format.c:handle_value_label:
   29|  12.0k|static int handle_value_label(const char *val_labels, readstat_value_t value, const char *label, void *ctx) {
   30|  12.0k|    return READSTAT_HANDLER_OK;
  ------------------
  |  |   22|  12.0k|#define READSTAT_HANDLER_OK             0
  ------------------
   31|  12.0k|}

LLVMFuzzerTestOneInput:
   10|  2.81k|int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
   11|  2.81k|    rt_buffer_t buffer = { .bytes = (char *)Data, .size = Size, .used = Size };
   12|  2.81k|    rt_buffer_ctx_t buffer_ctx = { .buffer = &buffer };
   13|       |
   14|  2.81k|    readstat_parser_t *parser = fuzzer_parser_init(Data, Size);
   15|  2.81k|    readstat_set_io_ctx(parser, &buffer_ctx);
   16|       |
   17|  2.81k|    readstat_parse_por(parser, NULL, NULL);
   18|  2.81k|    readstat_parser_free(parser);
   19|  2.81k|    return 0;
   20|  2.81k|}

readstat_convert:
   39|  22.2k|readstat_error_t readstat_convert(char *dst, size_t dst_len, const char *src, size_t src_len, iconv_t converter) {
   40|  22.2k|    return readstat_convert_impl(dst, dst_len, src, src_len, converter, 1);
   41|  22.2k|}
readstat_convert.c:readstat_convert_impl:
    8|  22.2k|        iconv_t converter, int trim_spaces) {
    9|       |    /* strip off spaces from the input because the programs use ASCII space
   10|       |     * padding even with non-ASCII encoding. */
   11|  94.0k|    while (src_len && ((trim_spaces && src[src_len-1] == ' ') || src[src_len-1] == '\0')) {
  ------------------
  |  Branch (11:12): [True: 85.3k, False: 8.65k]
  |  Branch (11:25): [True: 85.3k, False: 0]
  |  Branch (11:40): [True: 61.4k, False: 23.9k]
  |  Branch (11:66): [True: 10.3k, False: 13.5k]
  ------------------
   12|  71.7k|        src_len--;
   13|  71.7k|    }
   14|  22.2k|    if (dst_len == 0) {
  ------------------
  |  Branch (14:9): [True: 0, False: 22.2k]
  ------------------
   15|      0|        return READSTAT_ERROR_CONVERT_LONG_STRING;
   16|  22.2k|    } else if (converter) {
  ------------------
  |  Branch (16:16): [True: 0, False: 22.2k]
  ------------------
   17|      0|        size_t dst_left = dst_len - 1;
   18|      0|        char *dst_end = dst;
   19|      0|        size_t status = iconv(converter, (readstat_iconv_inbuf_t)&src, &src_len, &dst_end, &dst_left);
   20|      0|        if (status == (size_t)-1) {
  ------------------
  |  Branch (20:13): [True: 0, False: 0]
  ------------------
   21|      0|            if (errno == E2BIG) {
  ------------------
  |  Branch (21:17): [True: 0, False: 0]
  ------------------
   22|      0|                return READSTAT_ERROR_CONVERT_LONG_STRING;
   23|      0|            } else if (errno == EILSEQ) {
  ------------------
  |  Branch (23:24): [True: 0, False: 0]
  ------------------
   24|      0|                return READSTAT_ERROR_CONVERT_BAD_STRING;
   25|      0|            } else if (errno != EINVAL) { /* EINVAL indicates improper truncation; accept it */
  ------------------
  |  Branch (25:24): [True: 0, False: 0]
  ------------------
   26|      0|                return READSTAT_ERROR_CONVERT;
   27|      0|            }
   28|      0|        }
   29|      0|        dst[dst_len - dst_left - 1] = '\0';
   30|  22.2k|    } else if (src_len + 1 > dst_len) {
  ------------------
  |  Branch (30:16): [True: 0, False: 22.2k]
  ------------------
   31|      0|        return READSTAT_ERROR_CONVERT_LONG_STRING;
   32|  22.2k|    } else {
   33|  22.2k|        memcpy(dst, src, src_len);
   34|  22.2k|        dst[src_len] = '\0';
   35|  22.2k|    }
   36|  22.2k|    return READSTAT_OK;
   37|  22.2k|}

unistd_io_init:
  121|  2.81k|readstat_error_t unistd_io_init(readstat_parser_t *parser) {
  122|  2.81k|    readstat_error_t retval = READSTAT_OK;
  123|  2.81k|    unistd_io_ctx_t *io_ctx = NULL;
  124|       |
  125|  2.81k|    if ((retval = readstat_set_open_handler(parser, unistd_open_handler)) != READSTAT_OK)
  ------------------
  |  Branch (125:9): [True: 0, False: 2.81k]
  ------------------
  126|      0|        return retval;
  127|       |
  128|  2.81k|    if ((retval = readstat_set_close_handler(parser, unistd_close_handler)) != READSTAT_OK)
  ------------------
  |  Branch (128:9): [True: 0, False: 2.81k]
  ------------------
  129|      0|        return retval;
  130|       |
  131|  2.81k|    if ((retval = readstat_set_seek_handler(parser, unistd_seek_handler)) != READSTAT_OK)
  ------------------
  |  Branch (131:9): [True: 0, False: 2.81k]
  ------------------
  132|      0|        return retval;
  133|       |
  134|  2.81k|    if ((retval = readstat_set_read_handler(parser, unistd_read_handler)) != READSTAT_OK)
  ------------------
  |  Branch (134:9): [True: 0, False: 2.81k]
  ------------------
  135|      0|        return retval;
  136|       |
  137|  2.81k|    if ((readstat_set_update_handler(parser, unistd_update_handler)) != READSTAT_OK)
  ------------------
  |  Branch (137:9): [True: 0, False: 2.81k]
  ------------------
  138|      0|        return retval;
  139|       |
  140|  2.81k|    io_ctx = calloc(1, sizeof(unistd_io_ctx_t));
  141|  2.81k|    io_ctx->fd = -1;
  142|       |
  143|  2.81k|    retval = readstat_set_io_ctx(parser, (void*) io_ctx);
  144|  2.81k|    parser->io->io_ctx_needs_free = 1;
  145|       |
  146|  2.81k|    return retval;
  147|  2.81k|}

readstat_calloc:
   17|  2.33k|void *readstat_calloc(size_t count, size_t size) {
   18|  2.33k|    if (count > MAX_MALLOC_SIZE || size > MAX_MALLOC_SIZE || count * size > MAX_MALLOC_SIZE) {
  ------------------
  |  |    3|  4.66k|#define MAX_MALLOC_SIZE 0x1000000
  ------------------
                  if (count > MAX_MALLOC_SIZE || size > MAX_MALLOC_SIZE || count * size > MAX_MALLOC_SIZE) {
  ------------------
  |  |    3|  4.66k|#define MAX_MALLOC_SIZE 0x1000000
  ------------------
                  if (count > MAX_MALLOC_SIZE || size > MAX_MALLOC_SIZE || count * size > MAX_MALLOC_SIZE) {
  ------------------
  |  |    3|  2.33k|#define MAX_MALLOC_SIZE 0x1000000
  ------------------
  |  Branch (18:9): [True: 0, False: 2.33k]
  |  Branch (18:36): [True: 0, False: 2.33k]
  |  Branch (18:62): [True: 6, False: 2.32k]
  ------------------
   19|      6|        return NULL;
   20|      6|    }
   21|  2.32k|    if (count == 0 || size == 0) {
  ------------------
  |  Branch (21:9): [True: 4, False: 2.32k]
  |  Branch (21:23): [True: 0, False: 2.32k]
  ------------------
   22|      4|        return NULL;
   23|      4|    }
   24|  2.32k|    return calloc(count, size);
   25|  2.32k|}

readstat_parser_init:
    6|  2.81k|readstat_parser_t *readstat_parser_init(void) {
    7|  2.81k|    readstat_parser_t *parser = calloc(1, sizeof(readstat_parser_t));
    8|  2.81k|    parser->io = calloc(1, sizeof(readstat_io_t));
    9|  2.81k|    if (unistd_io_init(parser) != READSTAT_OK) {
  ------------------
  |  Branch (9:9): [True: 0, False: 2.81k]
  ------------------
   10|      0|        readstat_parser_free(parser);
   11|      0|        return NULL;
   12|      0|    }
   13|  2.81k|    parser->output_encoding = "UTF-8";
   14|  2.81k|    return parser;
   15|  2.81k|}
readstat_parser_free:
   17|  2.81k|void readstat_parser_free(readstat_parser_t *parser) {
   18|  2.81k|    if (parser) {
  ------------------
  |  Branch (18:9): [True: 2.81k, False: 0]
  ------------------
   19|  2.81k|        if (parser->io) {
  ------------------
  |  Branch (19:13): [True: 2.81k, False: 0]
  ------------------
   20|       |            readstat_set_io_ctx(parser, NULL);
   21|  2.81k|            free(parser->io);
   22|  2.81k|        }
   23|  2.81k|        free(parser);
   24|  2.81k|    }
   25|  2.81k|}
readstat_set_metadata_handler:
   27|  2.81k|readstat_error_t readstat_set_metadata_handler(readstat_parser_t *parser, readstat_metadata_handler metadata_handler) {
   28|  2.81k|    parser->handlers.metadata = metadata_handler;
   29|  2.81k|    return READSTAT_OK;
   30|  2.81k|}
readstat_set_note_handler:
   32|  2.81k|readstat_error_t readstat_set_note_handler(readstat_parser_t *parser, readstat_note_handler note_handler) {
   33|  2.81k|    parser->handlers.note = note_handler;
   34|  2.81k|    return READSTAT_OK;
   35|  2.81k|}
readstat_set_variable_handler:
   37|  2.81k|readstat_error_t readstat_set_variable_handler(readstat_parser_t *parser, readstat_variable_handler variable_handler) {
   38|  2.81k|    parser->handlers.variable = variable_handler;
   39|  2.81k|    return READSTAT_OK;
   40|  2.81k|}
readstat_set_value_handler:
   42|  2.81k|readstat_error_t readstat_set_value_handler(readstat_parser_t *parser, readstat_value_handler value_handler) {
   43|  2.81k|    parser->handlers.value = value_handler;
   44|  2.81k|    return READSTAT_OK;
   45|  2.81k|}
readstat_set_value_label_handler:
   47|  2.81k|readstat_error_t readstat_set_value_label_handler(readstat_parser_t *parser, readstat_value_label_handler label_handler) {
   48|  2.81k|    parser->handlers.value_label = label_handler;
   49|  2.81k|    return READSTAT_OK;
   50|  2.81k|}
readstat_set_fweight_handler:
   62|  2.81k|readstat_error_t readstat_set_fweight_handler(readstat_parser_t *parser, readstat_fweight_handler fweight_handler) {
   63|  2.81k|    parser->handlers.fweight = fweight_handler;
   64|  2.81k|    return READSTAT_OK;
   65|  2.81k|}
readstat_set_open_handler:
   67|  5.62k|readstat_error_t readstat_set_open_handler(readstat_parser_t *parser, readstat_open_handler open_handler) {
   68|  5.62k|    parser->io->open = open_handler;
   69|  5.62k|    return READSTAT_OK;
   70|  5.62k|}
readstat_set_close_handler:
   72|  5.62k|readstat_error_t readstat_set_close_handler(readstat_parser_t *parser, readstat_close_handler close_handler) {
   73|  5.62k|    parser->io->close = close_handler;
   74|  5.62k|    return READSTAT_OK;
   75|  5.62k|}
readstat_set_seek_handler:
   77|  5.62k|readstat_error_t readstat_set_seek_handler(readstat_parser_t *parser, readstat_seek_handler seek_handler) {
   78|  5.62k|    parser->io->seek = seek_handler;
   79|  5.62k|    return READSTAT_OK;
   80|  5.62k|}
readstat_set_read_handler:
   82|  5.62k|readstat_error_t readstat_set_read_handler(readstat_parser_t *parser, readstat_read_handler read_handler) {
   83|  5.62k|    parser->io->read = read_handler;
   84|  5.62k|    return READSTAT_OK;
   85|  5.62k|}
readstat_set_update_handler:
   87|  5.62k|readstat_error_t readstat_set_update_handler(readstat_parser_t *parser, readstat_update_handler update_handler) {
   88|  5.62k|    parser->io->update = update_handler;
   89|  5.62k|    return READSTAT_OK;
   90|  5.62k|}
readstat_set_io_ctx:
   92|  8.43k|readstat_error_t readstat_set_io_ctx(readstat_parser_t *parser, void *io_ctx) {
   93|  8.43k|    if (parser->io->io_ctx_needs_free) {
  ------------------
  |  Branch (93:9): [True: 2.81k, False: 5.62k]
  ------------------
   94|  2.81k|        free(parser->io->io_ctx);
   95|  2.81k|    }
   96|       |
   97|  8.43k|    parser->io->io_ctx = io_ctx;
   98|  8.43k|    parser->io->io_ctx_needs_free = 0;
   99|       |
  100|  8.43k|    return READSTAT_OK;
  101|  8.43k|}

por_ctx_init:
   75|  2.81k|por_ctx_t *por_ctx_init(void) {
   76|  2.81k|    por_ctx_t *ctx = calloc(1, sizeof(por_ctx_t));
   77|       |
   78|  2.81k|    ctx->space = ' ';
   79|  2.81k|    ctx->base30_precision = 20;
   80|  2.81k|    ctx->var_dict = ck_hash_table_init(1024, 8);
   81|  2.81k|    return ctx;
   82|  2.81k|}
por_ctx_free:
   84|  2.81k|void por_ctx_free(por_ctx_t *ctx) {
   85|  2.81k|    if (ctx->string_buffer)
  ------------------
  |  Branch (85:9): [True: 1.87k, False: 939]
  ------------------
   86|  1.87k|        free(ctx->string_buffer);
   87|  2.81k|    if (ctx->varinfo) {
  ------------------
  |  Branch (87:9): [True: 1.15k, False: 1.65k]
  ------------------
   88|  1.15k|        int i;
   89|  2.63M|        for (i=0; i<ctx->var_count; i++) {
  ------------------
  |  Branch (89:19): [True: 2.63M, False: 1.15k]
  ------------------
   90|  2.63M|            if (ctx->varinfo[i].label)
  ------------------
  |  Branch (90:17): [True: 777, False: 2.63M]
  ------------------
   91|    777|                free(ctx->varinfo[i].label);
   92|  2.63M|        }
   93|  1.15k|        free(ctx->varinfo);
   94|  1.15k|    }
   95|  2.81k|    if (ctx->variables) {
  ------------------
  |  Branch (95:9): [True: 1.16k, False: 1.64k]
  ------------------
   96|  1.16k|        int i;
   97|  5.86M|        for (i=0; i<ctx->var_count; i++) {
  ------------------
  |  Branch (97:19): [True: 5.86M, False: 1.16k]
  ------------------
   98|  5.86M|            if (ctx->variables[i])
  ------------------
  |  Branch (98:17): [True: 1.66k, False: 5.86M]
  ------------------
   99|  1.66k|                free(ctx->variables[i]);
  100|  5.86M|        }
  101|  1.16k|        free(ctx->variables);
  102|  1.16k|    }
  103|  2.81k|    if (ctx->var_dict)
  ------------------
  |  Branch (103:9): [True: 2.81k, False: 0]
  ------------------
  104|  2.81k|        ck_hash_table_free(ctx->var_dict);
  105|  2.81k|    if (ctx->converter)
  ------------------
  |  Branch (105:9): [True: 0, False: 2.81k]
  ------------------
  106|      0|        iconv_close(ctx->converter);
  107|  2.81k|    free(ctx);
  108|  2.81k|}
por_utf8_encode:
  168|   199k|        char *output, size_t output_len, uint16_t lookup[256]) {
  169|   199k|    size_t offset = 0;
  170|   199k|    size_t i;
  171|  2.96M|    for (i=0; i<input_len; i++) {
  ------------------
  |  Branch (171:15): [True: 2.76M, False: 194k]
  ------------------
  172|  2.76M|        uint16_t codepoint = lookup[input[i]];
  173|       |
  174|       |        /* Some software (SPSS?) uses an undefined character (zero) if a
  175|       |         * character can't be encoded. Use Unicode replacement character */
  176|  2.76M|        if (codepoint == 0) {
  ------------------
  |  Branch (176:13): [True: 24.9k, False: 2.74M]
  ------------------
  177|  24.9k|            codepoint = 0xFFFD;
  178|  24.9k|        }
  179|       |
  180|  2.76M|        if (codepoint < 0x20) {
  ------------------
  |  Branch (180:13): [True: 0, False: 2.76M]
  ------------------
  181|      0|            return -1;
  182|  2.76M|        } else if (codepoint <= 0x7F) {
  ------------------
  |  Branch (182:20): [True: 2.74M, False: 25.5k]
  ------------------
  183|  2.74M|            if (offset + 1 > output_len)
  ------------------
  |  Branch (183:17): [True: 2.03k, False: 2.74M]
  ------------------
  184|  2.03k|                return offset;
  185|       |
  186|  2.74M|            output[offset++] = codepoint;
  187|  2.74M|        } else if (codepoint <= 0x07FF) {
  ------------------
  |  Branch (187:20): [True: 585, False: 24.9k]
  ------------------
  188|    585|            if (offset + 2 > output_len)
  ------------------
  |  Branch (188:17): [True: 196, False: 389]
  ------------------
  189|    196|                return offset;
  190|       |
  191|    389|            output[offset++] = 0xC0 | (codepoint >> 6);
  192|    389|            output[offset++] = 0x80 | (codepoint & 0x3F);
  193|  24.9k|        } else {
  194|  24.9k|            if (offset + 3 > output_len)
  ------------------
  |  Branch (194:17): [True: 2.74k, False: 22.2k]
  ------------------
  195|  2.74k|                return offset;
  196|       |
  197|  22.2k|            output[offset++] = 0xE0 | (codepoint >> 12);
  198|  22.2k|            output[offset++] = 0x80 | ((codepoint >> 6) & 0x3F);
  199|  22.2k|            output[offset++] = 0x80 | (codepoint & 0x3F);
  200|  22.2k|        }
  201|  2.76M|    }
  202|   194k|    return offset;
  203|   199k|}
por_base30_to_double:
  399|   158k|double por_base30_to_double(const unsigned char *digits, size_t n_digits, long exponent) {
  400|   158k|    uint64_t mantissa = 0;
  401|   158k|    size_t mantissa_digits = 0;
  402|   158k|    long magnitude = 0;
  403|   158k|    long scale = 0;
  404|   158k|    double value = 0.0;
  405|   158k|    int iterations = 0;
  406|       |
  407|   158k|    while (n_digits > 0 && digits[0] == 0) {
  ------------------
  |  Branch (407:12): [True: 116k, False: 42.0k]
  |  Branch (407:28): [True: 0, False: 116k]
  ------------------
  408|      0|        digits++;
  409|      0|        n_digits--;
  410|      0|    }
  411|   224k|    while (n_digits > 0 && digits[n_digits-1] == 0) {
  ------------------
  |  Branch (411:12): [True: 182k, False: 42.0k]
  |  Branch (411:28): [True: 66.2k, False: 116k]
  ------------------
  412|  66.2k|        n_digits--;
  413|  66.2k|        exponent++;
  414|  66.2k|    }
  415|   158k|    if (n_digits == 0)
  ------------------
  |  Branch (415:9): [True: 42.0k, False: 116k]
  ------------------
  416|  42.0k|        return 0.0;
  417|       |
  418|       |    /* The value lies in [30^(magnitude-1), 30^magnitude) */
  419|   116k|    magnitude = (long)n_digits + exponent;
  420|   116k|    if (magnitude >= 210) /* 30^209 exceeds DBL_MAX */
  ------------------
  |  Branch (420:9): [True: 746, False: 115k]
  ------------------
  421|    746|        return HUGE_VAL;
  422|   115k|    if (magnitude <= -225) /* 30^-225 is below half the smallest denormal */
  ------------------
  |  Branch (422:9): [True: 1.17k, False: 114k]
  ------------------
  423|  1.17k|        return 0.0;
  424|       |
  425|       |    /* Initial approximation from the leading 13 digits (30^13 < 2^64) */
  426|   487k|    while (mantissa_digits < n_digits && mantissa_digits < 13) {
  ------------------
  |  Branch (426:12): [True: 387k, False: 100k]
  |  Branch (426:42): [True: 373k, False: 13.9k]
  ------------------
  427|   373k|        mantissa = mantissa * 30 + digits[mantissa_digits];
  428|   373k|        mantissa_digits++;
  429|   373k|    }
  430|   114k|    scale = exponent + (long)(n_digits - mantissa_digits);
  431|       |
  432|   114k|    if (mantissa <= (1ULL << 53) && scale >= -13 && scale <= 13) {
  ------------------
  |  Branch (432:9): [True: 95.4k, False: 18.9k]
  |  Branch (432:37): [True: 92.3k, False: 3.07k]
  |  Branch (432:53): [True: 91.2k, False: 1.14k]
  ------------------
  433|       |        /* Both operands are exact, so the single multiplication or division
  434|       |         * below is correctly rounded (30^13 = 2^13 * 15^13 and 15^13 < 2^53) */
  435|  91.2k|        double pow30 = 1.0;
  436|  91.2k|        long k = scale < 0 ? -scale : scale;
  ------------------
  |  Branch (436:18): [True: 498, False: 90.7k]
  ------------------
  437|  97.3k|        while (k-- > 0)
  ------------------
  |  Branch (437:16): [True: 6.08k, False: 91.2k]
  ------------------
  438|  6.08k|            pow30 *= 30.0;
  439|  91.2k|        return scale < 0 ? (double)mantissa / pow30 : (double)mantissa * pow30;
  ------------------
  |  Branch (439:16): [True: 498, False: 90.7k]
  ------------------
  440|  91.2k|    }
  441|       |
  442|  23.2k|    value = (double)mantissa;
  443|  37.9k|    while (scale > 0) {
  ------------------
  |  Branch (443:12): [True: 14.6k, False: 23.2k]
  ------------------
  444|  14.6k|        long step = scale > 200 ? 200 : scale;
  ------------------
  |  Branch (444:21): [True: 389, False: 14.2k]
  ------------------
  445|  14.6k|        value *= pow(30.0, (double)step);
  446|  14.6k|        scale -= step;
  447|  14.6k|    }
  448|  29.1k|    while (scale < 0) {
  ------------------
  |  Branch (448:12): [True: 5.93k, False: 23.2k]
  ------------------
  449|  5.93k|        long step = scale < -200 ? -200 : scale;
  ------------------
  |  Branch (449:21): [True: 808, False: 5.12k]
  ------------------
  450|  5.93k|        value *= pow(30.0, (double)step);
  451|  5.93k|        scale -= step;
  452|  5.93k|    }
  453|  23.2k|    if (isinf(value))
  ------------------
  |  Branch (453:9): [True: 426, False: 22.7k]
  ------------------
  454|    426|        value = DBL_MAX;
  455|       |
  456|       |    /* Correct the approximation by comparing the exact value against the
  457|       |     * midpoints between the candidate and its neighbors, moving one ulp at a
  458|       |     * time. Ties round to even. */
  459|  30.8k|    for (iterations=0; iterations<256; iterations++) {
  ------------------
  |  Branch (459:24): [True: 30.8k, False: 0]
  ------------------
  460|  30.8k|        uint64_t m = 0;
  461|  30.8k|        long e = -1074;
  462|  30.8k|        uint64_t midpoint_mantissa = 0;
  463|  30.8k|        long midpoint_exponent = 0;
  464|  30.8k|        int cmp = 0;
  465|       |
  466|  30.8k|        if (isinf(value))
  ------------------
  |  Branch (466:13): [True: 426, False: 30.4k]
  ------------------
  467|    426|            break;
  468|       |
  469|  30.4k|        if (value != 0.0) {
  ------------------
  |  Branch (469:13): [True: 30.2k, False: 204]
  ------------------
  470|  30.2k|            int exp2 = 0;
  471|  30.2k|            double significand = frexp(value, &exp2);
  472|  30.2k|            m = (uint64_t)ldexp(significand, 53);
  473|  30.2k|            e = exp2 - 53;
  474|  30.2k|            if (e < -1074) {
  ------------------
  |  Branch (474:17): [True: 419, False: 29.7k]
  ------------------
  475|       |                /* denormal: the spacing is fixed at 2^-1074 */
  476|    419|                m = (uint64_t)ldexp(value, 1074);
  477|    419|                e = -1074;
  478|    419|            }
  479|  30.2k|        }
  480|       |
  481|       |        /* midpoint above: (2m + 1) * 2^(e - 1) */
  482|  30.4k|        midpoint_mantissa = 2 * m + 1;
  483|  30.4k|        midpoint_exponent = e - 1;
  484|  30.4k|        cmp = por_compare_with_binary(digits, n_digits, exponent, midpoint_mantissa, midpoint_exponent);
  485|  30.4k|        if (cmp == 2)
  ------------------
  |  Branch (485:13): [True: 0, False: 30.4k]
  ------------------
  486|      0|            break;
  487|  30.4k|        if (cmp > 0) {
  ------------------
  |  Branch (487:13): [True: 5.06k, False: 25.3k]
  ------------------
  488|  5.06k|            value = nextafter(value, HUGE_VAL);
  489|  5.06k|            continue;
  490|  5.06k|        }
  491|  25.3k|        if (cmp == 0) {
  ------------------
  |  Branch (491:13): [True: 781, False: 24.5k]
  ------------------
  492|    781|            if (m & 1)
  ------------------
  |  Branch (492:17): [True: 194, False: 587]
  ------------------
  493|    194|                value = nextafter(value, HUGE_VAL);
  494|    781|            break;
  495|    781|        }
  496|  24.5k|        if (m == 0)
  ------------------
  |  Branch (496:13): [True: 204, False: 24.3k]
  ------------------
  497|    204|            break;
  498|       |
  499|       |        /* midpoint below: the spacing halves just below a power of two */
  500|  24.3k|        if (m == (1ULL << 52) && e > -1074) {
  ------------------
  |  Branch (500:13): [True: 201, False: 24.1k]
  |  Branch (500:34): [True: 201, False: 0]
  ------------------
  501|    201|            midpoint_mantissa = 4 * m - 1;
  502|    201|            midpoint_exponent = e - 2;
  503|  24.1k|        } else {
  504|  24.1k|            midpoint_mantissa = 2 * m - 1;
  505|  24.1k|            midpoint_exponent = e - 1;
  506|  24.1k|        }
  507|  24.3k|        cmp = por_compare_with_binary(digits, n_digits, exponent, midpoint_mantissa, midpoint_exponent);
  508|  24.3k|        if (cmp == 2)
  ------------------
  |  Branch (508:13): [True: 0, False: 24.3k]
  ------------------
  509|      0|            break;
  510|  24.3k|        if (cmp < 0) {
  ------------------
  |  Branch (510:13): [True: 2.56k, False: 21.8k]
  ------------------
  511|  2.56k|            value = nextafter(value, 0.0);
  512|  2.56k|            continue;
  513|  2.56k|        }
  514|  21.8k|        if (cmp == 0) {
  ------------------
  |  Branch (514:13): [True: 2.41k, False: 19.3k]
  ------------------
  515|       |            /* value's mantissa is 2m in the finer grid below a power of two,
  516|       |             * which is even, so only the ordinary case can move */
  517|  2.41k|            if (midpoint_mantissa == 2 * m - 1 && (m & 1))
  ------------------
  |  Branch (517:17): [True: 2.41k, False: 1]
  |  Branch (517:51): [True: 322, False: 2.09k]
  ------------------
  518|    322|                value = nextafter(value, 0.0);
  519|  2.41k|            break;
  520|  2.41k|        }
  521|  19.3k|        break;
  522|  21.8k|    }
  523|       |
  524|  23.2k|    return value;
  525|   114k|}
readstat_por.c:por_big_set:
  249|   109k|static void por_big_set(por_bignum_t *big, uint64_t value) {
  250|   109k|    big->n = 0;
  251|   109k|    big->overflow = 0;
  252|   218k|    while (value) {
  ------------------
  |  Branch (252:12): [True: 108k, False: 109k]
  ------------------
  253|   108k|        big->limbs[big->n++] = (uint32_t)(value % POR_BIG_LIMB_BASE);
  ------------------
  |  |  239|   108k|#define POR_BIG_LIMB_BASE   729000000u  /* 30^6 */
  ------------------
  254|   108k|        value /= POR_BIG_LIMB_BASE;
  ------------------
  |  |  239|   108k|#define POR_BIG_LIMB_BASE   729000000u  /* 30^6 */
  ------------------
  255|   108k|    }
  256|   109k|}
readstat_por.c:por_big_mul_pow:
  279|  65.2k|static void por_big_mul_pow(por_bignum_t *big, uint32_t base, long exponent) {
  280|  65.2k|    uint32_t chunk_mult = 1;
  281|  65.2k|    long chunk = 0;
  282|  1.70M|    while ((uint64_t)chunk_mult * base <= 0xFFFFFFFFu) {
  ------------------
  |  Branch (282:12): [True: 1.63M, False: 65.2k]
  ------------------
  283|  1.63M|        chunk_mult *= base;
  284|  1.63M|        chunk++;
  285|  1.63M|    }
  286|   591k|    while (exponent >= chunk && !big->overflow) {
  ------------------
  |  Branch (286:12): [True: 526k, False: 65.2k]
  |  Branch (286:33): [True: 526k, False: 0]
  ------------------
  287|   526k|        por_big_mul_add(big, chunk_mult, 0);
  288|   526k|        exponent -= chunk;
  289|   526k|    }
  290|  65.2k|    if (exponent > 0) {
  ------------------
  |  Branch (290:9): [True: 61.4k, False: 3.76k]
  ------------------
  291|  61.4k|        uint32_t mult = 1;
  292|   840k|        while (exponent-- > 0)
  ------------------
  |  Branch (292:16): [True: 779k, False: 61.4k]
  ------------------
  293|   779k|            mult *= base;
  294|  61.4k|        por_big_mul_add(big, mult, 0);
  295|  61.4k|    }
  296|  65.2k|}
readstat_por.c:por_big_mul_add:
  259|   859k|static void por_big_mul_add(por_bignum_t *big, uint32_t mult, uint32_t add) {
  260|   859k|    uint64_t carry = add;
  261|   859k|    int i;
  262|  8.95M|    for (i=0; i<big->n; i++) {
  ------------------
  |  Branch (262:15): [True: 8.09M, False: 859k]
  ------------------
  263|  8.09M|        uint64_t product = (uint64_t)big->limbs[i] * mult + carry;
  264|  8.09M|        big->limbs[i] = (uint32_t)(product % POR_BIG_LIMB_BASE);
  ------------------
  |  |  239|  8.09M|#define POR_BIG_LIMB_BASE   729000000u  /* 30^6 */
  ------------------
  265|  8.09M|        carry = product / POR_BIG_LIMB_BASE;
  ------------------
  |  |  239|  8.09M|#define POR_BIG_LIMB_BASE   729000000u  /* 30^6 */
  ------------------
  266|  8.09M|    }
  267|  1.71M|    while (carry) {
  ------------------
  |  Branch (267:12): [True: 859k, False: 859k]
  ------------------
  268|   859k|        if (big->n == POR_BIG_LIMBS) {
  ------------------
  |  |  241|   859k|#define POR_BIG_LIMBS       200         /* 1200 trigesimals; a denormal needs ~870 */
  ------------------
  |  Branch (268:13): [True: 0, False: 859k]
  ------------------
  269|      0|            big->overflow = 1;
  270|      0|            return;
  271|      0|        }
  272|   859k|        big->limbs[big->n++] = (uint32_t)(carry % POR_BIG_LIMB_BASE);
  ------------------
  |  |  239|   859k|#define POR_BIG_LIMB_BASE   729000000u  /* 30^6 */
  ------------------
  273|   859k|        carry /= POR_BIG_LIMB_BASE;
  ------------------
  |  |  239|   859k|#define POR_BIG_LIMB_BASE   729000000u  /* 30^6 */
  ------------------
  274|   859k|    }
  275|   859k|}
readstat_por.c:por_compare_with_binary:
  362|  54.7k|        uint64_t mantissa, long exp2) {
  363|  54.7k|    por_bignum_t lhs, rhs;
  364|  54.7k|    size_t i;
  365|  54.7k|    uint32_t chunk = 0;
  366|  54.7k|    uint32_t chunk_mult = 1;
  367|       |
  368|  54.7k|    por_big_set(&lhs, 0);
  369|  1.54M|    for (i=0; i<n_digits; i++) {
  ------------------
  |  Branch (369:15): [True: 1.49M, False: 54.7k]
  ------------------
  370|  1.49M|        chunk = chunk * 30 + digits[i];
  371|  1.49M|        chunk_mult *= 30;
  372|  1.49M|        if (chunk_mult == POR_BIG_LIMB_BASE) {
  ------------------
  |  |  239|  1.49M|#define POR_BIG_LIMB_BASE   729000000u  /* 30^6 */
  ------------------
  |  Branch (372:13): [True: 225k, False: 1.26M]
  ------------------
  373|   225k|            por_big_mul_add(&lhs, chunk_mult, chunk);
  374|   225k|            chunk = 0;
  375|   225k|            chunk_mult = 1;
  376|   225k|        }
  377|  1.49M|    }
  378|  54.7k|    if (chunk_mult > 1)
  ------------------
  |  Branch (378:9): [True: 45.7k, False: 9.01k]
  ------------------
  379|  45.7k|        por_big_mul_add(&lhs, chunk_mult, chunk);
  380|       |
  381|  54.7k|    por_big_set(&rhs, mantissa);
  382|       |
  383|  54.7k|    if (exp30 > 0) {
  ------------------
  |  Branch (383:9): [True: 3.56k, False: 51.2k]
  ------------------
  384|  3.56k|        por_big_mul_pow(&lhs, 30, exp30);
  385|  51.2k|    } else if (exp30 < 0) {
  ------------------
  |  Branch (385:16): [True: 11.8k, False: 39.3k]
  ------------------
  386|  11.8k|        por_big_mul_pow(&rhs, 30, -exp30);
  387|  11.8k|    }
  388|  54.7k|    if (exp2 > 0) {
  ------------------
  |  Branch (388:9): [True: 38.1k, False: 16.6k]
  ------------------
  389|  38.1k|        por_big_mul_pow(&rhs, 2, exp2);
  390|  38.1k|    } else if (exp2 < 0) {
  ------------------
  |  Branch (390:16): [True: 11.6k, False: 4.99k]
  ------------------
  391|  11.6k|        por_big_mul_pow(&lhs, 2, -exp2);
  392|  11.6k|    }
  393|  54.7k|    if (lhs.overflow || rhs.overflow)
  ------------------
  |  Branch (393:9): [True: 0, False: 54.7k]
  |  Branch (393:25): [True: 0, False: 54.7k]
  ------------------
  394|      0|        return 2;
  395|       |
  396|  54.7k|    return por_big_compare(&lhs, &rhs);
  397|  54.7k|}
readstat_por.c:por_big_compare:
  298|  54.7k|static int por_big_compare(const por_bignum_t *a, const por_bignum_t *b) {
  299|  54.7k|    int i;
  300|  54.7k|    if (a->n != b->n)
  ------------------
  |  Branch (300:9): [True: 378, False: 54.4k]
  ------------------
  301|    378|        return a->n > b->n ? 1 : -1;
  ------------------
  |  Branch (301:16): [True: 167, False: 211]
  ------------------
  302|   148k|    for (i=a->n-1; i>=0; i--) {
  ------------------
  |  Branch (302:20): [True: 144k, False: 3.20k]
  ------------------
  303|   144k|        if (a->limbs[i] != b->limbs[i])
  ------------------
  |  Branch (303:13): [True: 51.2k, False: 93.7k]
  ------------------
  304|  51.2k|            return a->limbs[i] > b->limbs[i] ? 1 : -1;
  ------------------
  |  Branch (304:20): [True: 24.2k, False: 26.9k]
  ------------------
  305|   144k|    }
  306|  3.20k|    return 0;
  307|  54.4k|}

readstat_por_parse_double:
   79|   158k|readstat_error_handler error_cb, void *user_ctx) {
   80|   158k|	ssize_t retval = 0;
   81|   158k|	double val = 0.0;
   82|       |	
   83|       |	/* Significant digits of the mantissa, most significant first; leading
   84|       |	* zeros are dropped and digits beyond POR_PARSE_MAX_DIGITS are folded
   85|       |	* into the scale. */
   86|   158k|	unsigned char digits[POR_PARSE_MAX_DIGITS] = { 0 };
   87|   158k|	size_t n_digits = 0;
   88|   158k|	long scale = 0;
   89|   158k|	long exp = 0;
   90|       |	
   91|   158k|	const unsigned char *p = (const unsigned char *)data;
   92|   158k|	const unsigned char *pe = p + len;
   93|       |	
   94|   158k|	int cs;
   95|   158k|	int is_negative = 0, exp_is_negative = 0;
   96|   158k|	int got_dot = 0;
   97|   158k|	int is_missing = 0;
   98|   158k|	int success = 0;
   99|       |	
  100|       |	
  101|   158k|#line 102 "src/spss/readstat_por_parse.c"
  102|   158k|	{
  103|   158k|		cs = (int)por_field_parse_start;
  104|   158k|	}
  105|       |	
  106|   158k|#line 107 "src/spss/readstat_por_parse.c"
  107|   158k|	{
  108|   158k|		int _klen;
  109|   158k|		unsigned int _trans = 0;
  110|   158k|		const char * _keys;
  111|   158k|		const signed char * _acts;
  112|   158k|		unsigned int _nacts;
  113|  2.22M|		_resume: {}
  114|  2.22M|		if ( p == pe )
  ------------------
  |  Branch (114:8): [True: 0, False: 2.22M]
  ------------------
  115|      0|			goto _out;
  116|  2.22M|		_keys = ( _por_field_parse_trans_keys + (_por_field_parse_key_offsets[cs]));
  117|  2.22M|		_trans = (unsigned int)_por_field_parse_index_offsets[cs];
  118|       |		
  119|  2.22M|		_klen = (int)_por_field_parse_single_lengths[cs];
  120|  2.22M|		if ( _klen > 0 ) {
  ------------------
  |  Branch (120:8): [True: 2.22M, False: 7.72k]
  ------------------
  121|  2.22M|			const char *_lower = _keys;
  122|  2.22M|			const char *_upper = _keys + _klen - 1;
  123|  2.22M|			const char *_mid;
  124|  8.16M|			while ( 1 ) {
  ------------------
  |  Branch (124:12): [True: 8.16M, Folded]
  ------------------
  125|  8.16M|				if ( _upper < _lower ) {
  ------------------
  |  Branch (125:10): [True: 1.87M, False: 6.28M]
  ------------------
  126|  1.87M|					_keys += _klen;
  127|  1.87M|					_trans += (unsigned int)_klen;
  128|  1.87M|					break;
  129|  1.87M|				}
  130|       |				
  131|  6.28M|				_mid = _lower + ((_upper-_lower) >> 1);
  132|  6.28M|				if ( ( (*( p))) < (*( _mid)) )
  ------------------
  |  Branch (132:10): [True: 176k, False: 6.11M]
  ------------------
  133|   176k|					_upper = _mid - 1;
  134|  6.11M|				else if ( ( (*( p))) > (*( _mid)) )
  ------------------
  |  Branch (134:15): [True: 5.76M, False: 342k]
  ------------------
  135|  5.76M|					_lower = _mid + 1;
  136|   342k|				else {
  137|   342k|					_trans += (unsigned int)(_mid - _keys);
  138|   342k|					goto _match;
  139|   342k|				}
  140|  6.28M|			}
  141|  2.22M|		}
  142|       |		
  143|  1.88M|		_klen = (int)_por_field_parse_range_lengths[cs];
  144|  1.88M|		if ( _klen > 0 ) {
  ------------------
  |  Branch (144:8): [True: 1.88M, False: 1]
  ------------------
  145|  1.88M|			const char *_lower = _keys;
  146|  1.88M|			const char *_upper = _keys + (_klen<<1) - 2;
  147|  1.88M|			const char *_mid;
  148|  2.31M|			while ( 1 ) {
  ------------------
  |  Branch (148:12): [True: 2.31M, Folded]
  ------------------
  149|  2.31M|				if ( _upper < _lower ) {
  ------------------
  |  Branch (149:10): [True: 95, False: 2.31M]
  ------------------
  150|     95|					_trans += (unsigned int)_klen;
  151|     95|					break;
  152|     95|				}
  153|       |				
  154|  2.31M|				_mid = _lower + (((_upper-_lower) >> 1) & ~1);
  155|  2.31M|				if ( ( (*( p))) < (*( _mid)) )
  ------------------
  |  Branch (155:10): [True: 48, False: 2.31M]
  ------------------
  156|     48|					_upper = _mid - 2;
  157|  2.31M|				else if ( ( (*( p))) > (*( _mid + 1)) )
  ------------------
  |  Branch (157:15): [True: 428k, False: 1.88M]
  ------------------
  158|   428k|					_lower = _mid + 2;
  159|  1.88M|				else {
  160|  1.88M|					_trans += (unsigned int)((_mid - _keys)>>1);
  161|  1.88M|					break;
  162|  1.88M|				}
  163|  2.31M|			}
  164|  1.88M|		}
  165|       |		
  166|  2.22M|		_match: {}
  167|  2.22M|		cs = (int)_por_field_parse_cond_targs[_trans];
  168|       |		
  169|  2.22M|		if ( _por_field_parse_cond_actions[_trans] != 0 ) {
  ------------------
  |  Branch (169:8): [True: 2.05M, False: 176k]
  ------------------
  170|       |			
  171|  2.05M|			_acts = ( _por_field_parse_actions + (_por_field_parse_cond_actions[_trans]));
  172|  2.05M|			_nacts = (unsigned int)(*( _acts));
  173|  2.05M|			_acts += 1;
  174|  3.94M|			while ( _nacts > 0 ) {
  ------------------
  |  Branch (174:12): [True: 2.05M, False: 1.89M]
  ------------------
  175|  2.05M|				switch ( (*( _acts)) )
  ------------------
  |  Branch (175:14): [True: 2.05M, False: 0]
  ------------------
  176|  2.05M|				{
  177|  1.82M|					case 0:  {
  ------------------
  |  Branch (177:6): [True: 1.82M, False: 231k]
  ------------------
  178|  1.82M|						{
  179|  1.82M|#line 42 "src/spss/readstat_por_parse.rl"
  180|       |							
  181|  1.82M|							int digit = por_base30_digit_value((( (*( p)))));
  182|  1.82M|							if (n_digits == 0 && digit == 0) {
  ------------------
  |  Branch (182:12): [True: 1.16M, False: 652k]
  |  Branch (182:29): [True: 1.05M, False: 116k]
  ------------------
  183|  1.05M|								if (got_dot)
  ------------------
  |  Branch (183:13): [True: 921, False: 1.05M]
  ------------------
  184|    921|								scale--;
  185|  1.05M|							} else if (n_digits < POR_PARSE_MAX_DIGITS) {
  ------------------
  |  |    7|   768k|#define POR_PARSE_MAX_DIGITS 128
  ------------------
  |  Branch (185:19): [True: 768k, False: 0]
  ------------------
  186|   768k|								digits[n_digits++] = digit;
  187|   768k|								if (got_dot)
  ------------------
  |  Branch (187:13): [True: 54.6k, False: 714k]
  ------------------
  188|  54.6k|								scale--;
  189|   768k|							} else if (!got_dot) {
  ------------------
  |  Branch (189:19): [True: 0, False: 0]
  ------------------
  190|      0|								scale++;
  191|      0|							}
  192|  1.82M|						}
  193|       |						
  194|  1.82M|#line 195 "src/spss/readstat_por_parse.c"
  195|       |						
  196|  1.82M|						break; 
  197|      0|					}
  198|  64.8k|					case 1:  {
  ------------------
  |  Branch (198:6): [True: 64.8k, False: 1.98M]
  ------------------
  199|  64.8k|						{
  200|  64.8k|#line 56 "src/spss/readstat_por_parse.rl"
  201|       |							
  202|  64.8k|							if (exp < 100000)
  ------------------
  |  Branch (202:12): [True: 39.6k, False: 25.1k]
  ------------------
  203|  39.6k|							exp = 30 * exp + por_base30_digit_value((( (*( p)))));
  204|  64.8k|						}
  205|       |						
  206|  64.8k|#line 207 "src/spss/readstat_por_parse.c"
  207|       |						
  208|  64.8k|						break; 
  209|      0|					}
  210|  1.23k|					case 2:  {
  ------------------
  |  Branch (210:6): [True: 1.23k, False: 2.05M]
  ------------------
  211|  1.23k|						{
  212|  1.23k|#line 63 "src/spss/readstat_por_parse.rl"
  213|  1.23k|							got_dot = 1; }
  214|       |						
  215|  1.23k|#line 216 "src/spss/readstat_por_parse.c"
  216|       |						
  217|  1.23k|						break; 
  218|      0|					}
  219|  1.03k|					case 3:  {
  ------------------
  |  Branch (219:6): [True: 1.03k, False: 2.05M]
  ------------------
  220|  1.03k|						{
  221|  1.03k|#line 64 "src/spss/readstat_por_parse.rl"
  222|  1.03k|							got_dot = 1; }
  223|       |						
  224|  1.03k|#line 225 "src/spss/readstat_por_parse.c"
  225|       |						
  226|  1.03k|						break; 
  227|      0|					}
  228|  5.15k|					case 4:  {
  ------------------
  |  Branch (228:6): [True: 5.15k, False: 2.04M]
  ------------------
  229|  5.15k|						{
  230|  5.15k|#line 66 "src/spss/readstat_por_parse.rl"
  231|  5.15k|							exp_is_negative = 1; }
  232|       |						
  233|  5.15k|#line 234 "src/spss/readstat_por_parse.c"
  234|       |						
  235|  5.15k|						break; 
  236|      0|					}
  237|    367|					case 5:  {
  ------------------
  |  Branch (237:6): [True: 367, False: 2.05M]
  ------------------
  238|    367|						{
  239|    367|#line 68 "src/spss/readstat_por_parse.rl"
  240|    367|							is_negative = 1; }
  241|       |						
  242|    367|#line 243 "src/spss/readstat_por_parse.c"
  243|       |						
  244|    367|						break; 
  245|      0|					}
  246|    194|					case 6:  {
  ------------------
  |  Branch (246:6): [True: 194, False: 2.05M]
  ------------------
  247|    194|						{
  248|    194|#line 70 "src/spss/readstat_por_parse.rl"
  249|    194|							is_missing = 1; }
  250|       |						
  251|    194|#line 252 "src/spss/readstat_por_parse.c"
  252|       |						
  253|    194|						break; 
  254|      0|					}
  255|   158k|					case 7:  {
  ------------------
  |  Branch (255:6): [True: 158k, False: 1.89M]
  ------------------
  256|   158k|						{
  257|   158k|#line 72 "src/spss/readstat_por_parse.rl"
  258|   158k|							success = 1; {p += 1; goto _out; } }
  259|       |						
  260|      0|#line 261 "src/spss/readstat_por_parse.c"
  261|       |						
  262|      0|						break; 
  263|      0|					}
  264|  2.05M|				}
  265|  1.89M|				_nacts -= 1;
  266|  1.89M|				_acts += 1;
  267|  1.89M|			}
  268|       |			
  269|  2.05M|		}
  270|       |		
  271|  2.07M|		if ( cs != 0 ) {
  ------------------
  |  Branch (271:8): [True: 2.07M, False: 96]
  ------------------
  272|  2.07M|			p += 1;
  273|  2.07M|			goto _resume;
  274|  2.07M|		}
  275|   158k|		_out: {}
  276|   158k|	}
  277|       |	
  278|      0|#line 76 "src/spss/readstat_por_parse.rl"
  279|       |	
  280|       |	
  281|   158k|	if (is_missing) {
  ------------------
  |  Branch (281:6): [True: 194, False: 158k]
  ------------------
  282|    194|		val = NAN;
  283|   158k|	} else {
  284|   158k|		if (exp_is_negative)
  ------------------
  |  Branch (284:7): [True: 5.15k, False: 153k]
  ------------------
  285|  5.15k|			exp = -exp;
  286|   158k|		val = por_base30_to_double(digits, n_digits, scale + exp);
  287|   158k|		if (is_negative)
  ------------------
  |  Branch (287:7): [True: 367, False: 158k]
  ------------------
  288|    367|			val = -val;
  289|   158k|	}
  290|       |	
  291|   158k|	if (!success) {
  ------------------
  |  Branch (291:6): [True: 96, False: 158k]
  ------------------
  292|     96|		retval = -1;
  293|     96|		if (error_cb) {
  ------------------
  |  Branch (293:7): [True: 0, False: 96]
  ------------------
  294|      0|			char error_buf[1024];
  295|      0|			snprintf(error_buf, sizeof(error_buf), "Read bytes: %ld   String: %.*s  Ending state: %d",
  296|      0|			(long)(p - (const unsigned char *)data), (int)len, data, cs);
  297|      0|			error_cb(error_buf, user_ctx);
  298|      0|		}
  299|     96|	}
  300|       |	
  301|   158k|	if (retval == 0) {
  ------------------
  |  Branch (301:6): [True: 158k, False: 96]
  ------------------
  302|   158k|		if (result)
  ------------------
  |  Branch (302:7): [True: 158k, False: 0]
  ------------------
  303|   158k|			*result = val;
  304|       |		
  305|   158k|		retval = (p - (const unsigned char *)data);
  306|   158k|	}
  307|       |	
  308|       |	/* suppress warning */
  309|   158k|	(void)por_field_parse_en_main;
  310|       |	
  311|   158k|	return retval;
  312|  2.07M|}
readstat_por_parse.c:por_base30_digit_value:
   72|  1.86M|static int por_base30_digit_value(unsigned char c) {
   73|  1.86M|	if (c >= '0' && c <= '9')
  ------------------
  |  Branch (73:6): [True: 1.86M, False: 0]
  |  Branch (73:18): [True: 1.43M, False: 424k]
  ------------------
   74|  1.43M|		return c - '0';
   75|   424k|	return 10 + c - 'A';
   76|  1.86M|}

read_version_and_timestamp:
  700|  2.48k|readstat_error_t read_version_and_timestamp(por_ctx_t *ctx) {
  701|  2.48k|    readstat_error_t retval = READSTAT_OK;
  702|  2.48k|    char string[256];
  703|  2.48k|    struct tm timestamp = { .tm_isdst = -1 };
  704|  2.48k|    unsigned char version;
  705|       |
  706|  2.48k|    if (read_bytes(ctx, &version, sizeof(version)) != sizeof(version)) {
  ------------------
  |  Branch (706:9): [True: 10, False: 2.47k]
  ------------------
  707|     10|        retval = READSTAT_ERROR_READ;
  708|     10|        goto cleanup;
  709|     10|    }
  710|  2.47k|    if ((retval = read_string(ctx, string, sizeof(string))) != READSTAT_OK) { /* creation date */
  ------------------
  |  Branch (710:9): [True: 487, False: 1.99k]
  ------------------
  711|    487|        goto cleanup;
  712|    487|    }
  713|  1.99k|    if (sscanf(string, "%04d%02d%02d", &timestamp.tm_year, &timestamp.tm_mon, &timestamp.tm_mday) != 3) {
  ------------------
  |  Branch (713:9): [True: 205, False: 1.78k]
  ------------------
  714|    205|        retval = READSTAT_ERROR_BAD_TIMESTAMP_STRING;
  715|    205|        goto cleanup;
  716|    205|    }
  717|  1.78k|    if ((retval = read_string(ctx, string, sizeof(string))) != READSTAT_OK) { /* creation time */
  ------------------
  |  Branch (717:9): [True: 36, False: 1.75k]
  ------------------
  718|     36|        goto cleanup;
  719|     36|    }
  720|  1.75k|    if (sscanf(string, "%02d%02d%02d", &timestamp.tm_hour, &timestamp.tm_min, &timestamp.tm_sec) != 3) {
  ------------------
  |  Branch (720:9): [True: 1.65k, False: 96]
  ------------------
  721|       |        /* optional */
  722|  1.65k|    }
  723|       |
  724|  1.75k|    timestamp.tm_year -= 1900;
  725|  1.75k|    timestamp.tm_mon--;
  726|       |
  727|  1.75k|    ctx->timestamp = mktime(&timestamp);
  728|  1.75k|    ctx->version = ctx->byte2unicode[version] - 'A';
  729|       |
  730|  2.48k|cleanup:
  731|  2.48k|    return retval;
  732|  1.75k|}
handle_variables:
  734|    380|readstat_error_t handle_variables(por_ctx_t *ctx) {
  735|    380|    readstat_error_t retval = READSTAT_OK;
  736|    380|    int i;
  737|    380|    int index_after_skipping = 0;
  738|  2.04k|    for (i=0; i<ctx->var_count; i++) {
  ------------------
  |  Branch (738:15): [True: 1.66k, False: 380]
  ------------------
  739|  1.66k|        char label_name_buf[256];
  740|  1.66k|        spss_varinfo_t *info = &ctx->varinfo[i];
  741|  1.66k|        info->index = i;
  742|       |
  743|  1.66k|        ctx->variables[i] = spss_init_variable_for_info(info, index_after_skipping, ctx->converter);
  744|       |
  745|  1.66k|        snprintf(label_name_buf, sizeof(label_name_buf), POR_LABEL_NAME_PREFIX "%d", info->labels_index);
  ------------------
  |  |   25|  1.66k|#define POR_LABEL_NAME_PREFIX   "labels"
  ------------------
  746|       |
  747|  1.66k|        int cb_retval = READSTAT_HANDLER_OK;
  ------------------
  |  |   22|  1.66k|#define READSTAT_HANDLER_OK             0
  ------------------
  748|       |
  749|  1.66k|        if (ctx->handle.variable) {
  ------------------
  |  Branch (749:13): [True: 1.66k, False: 0]
  ------------------
  750|  1.66k|            cb_retval = ctx->handle.variable(i, ctx->variables[i],
  751|  1.66k|                    info->labels_index == -1 ? NULL : label_name_buf,
  ------------------
  |  Branch (751:21): [True: 1.64k, False: 21]
  ------------------
  752|  1.66k|                    ctx->user_ctx);
  753|  1.66k|        }
  754|       |
  755|  1.66k|        if (cb_retval == READSTAT_HANDLER_ABORT) {
  ------------------
  |  |   23|  1.66k|#define READSTAT_HANDLER_ABORT          1
  ------------------
  |  Branch (755:13): [True: 0, False: 1.66k]
  ------------------
  756|      0|            retval = READSTAT_ERROR_USER_ABORT;
  757|      0|            goto cleanup;
  758|      0|        }
  759|       |
  760|  1.66k|        if (cb_retval == READSTAT_HANDLER_SKIP_VARIABLE) {
  ------------------
  |  |   24|  1.66k|#define READSTAT_HANDLER_SKIP_VARIABLE  2
  ------------------
  |  Branch (760:13): [True: 0, False: 1.66k]
  ------------------
  761|      0|            ctx->variables[i]->skip = 1;
  762|  1.66k|        } else {
  763|  1.66k|            index_after_skipping++;
  764|  1.66k|        }
  765|  1.66k|    }
  766|    380|    if (ctx->handle.fweight && ctx->fweight_name[0]) {
  ------------------
  |  Branch (766:9): [True: 380, False: 0]
  |  Branch (766:32): [True: 96, False: 284]
  ------------------
  767|    560|        for (i=0; i<ctx->var_count; i++) {
  ------------------
  |  Branch (767:19): [True: 467, False: 93]
  ------------------
  768|    467|            spss_varinfo_t *info = &ctx->varinfo[i];
  769|    467|            if (strcmp(info->name, ctx->fweight_name) == 0) {
  ------------------
  |  Branch (769:17): [True: 3, False: 464]
  ------------------
  770|      3|                if (ctx->handle.fweight(ctx->variables[i], ctx->user_ctx) != READSTAT_HANDLER_OK) {
  ------------------
  |  |   22|      3|#define READSTAT_HANDLER_OK             0
  ------------------
  |  Branch (770:21): [True: 0, False: 3]
  ------------------
  771|      0|                    retval = READSTAT_ERROR_USER_ABORT;
  772|      0|                    goto cleanup;
  773|      0|                }
  774|      3|                break;
  775|      3|            }
  776|    467|        }
  777|     96|    }
  778|    380|cleanup:
  779|    380|    return retval;
  780|    380|}
readstat_parse_por:
  782|  2.81k|readstat_error_t readstat_parse_por(readstat_parser_t *parser, const char *path, void *user_ctx) {
  783|  2.81k|    readstat_error_t retval = READSTAT_OK;
  784|  2.81k|    readstat_io_t *io = parser->io;
  785|  2.81k|    unsigned char reverse_lookup[256];
  786|  2.81k|    char vanity[5][40];
  787|  2.81k|    char error_buf[1024];
  788|       |
  789|  2.81k|    por_ctx_t *ctx = por_ctx_init();
  790|       |    
  791|  2.81k|    ctx->handle = parser->handlers;
  792|  2.81k|    ctx->user_ctx = user_ctx;
  793|  2.81k|    ctx->io = io;
  794|  2.81k|    ctx->row_limit = parser->row_limit;
  795|  2.81k|    if (parser->row_offset > 0)
  ------------------
  |  Branch (795:9): [True: 0, False: 2.81k]
  ------------------
  796|      0|        ctx->row_offset = parser->row_offset;
  797|       |
  798|  2.81k|    if (parser->output_encoding) {
  ------------------
  |  Branch (798:9): [True: 2.81k, False: 0]
  ------------------
  799|  2.81k|        if (strcmp(parser->output_encoding, "UTF-8") != 0)
  ------------------
  |  Branch (799:13): [True: 0, False: 2.81k]
  ------------------
  800|      0|            ctx->converter = iconv_open(parser->output_encoding, "UTF-8");
  801|       |
  802|  2.81k|        if (ctx->converter == (iconv_t)-1) {
  ------------------
  |  Branch (802:13): [True: 0, False: 2.81k]
  ------------------
  803|      0|            ctx->converter = NULL;
  804|      0|            retval = READSTAT_ERROR_UNSUPPORTED_CHARSET;
  805|      0|            goto cleanup;
  806|      0|        }
  807|  2.81k|    }
  808|       |    
  809|  2.81k|    if (io->open(path, io->io_ctx) == -1) {
  ------------------
  |  Branch (809:9): [True: 0, False: 2.81k]
  ------------------
  810|      0|        retval = READSTAT_ERROR_OPEN;
  811|      0|        goto cleanup;
  812|      0|    }
  813|       |
  814|  2.81k|    if ((ctx->file_size = io->seek(0, READSTAT_SEEK_END, io->io_ctx)) == -1) {
  ------------------
  |  Branch (814:9): [True: 0, False: 2.81k]
  ------------------
  815|      0|        retval = READSTAT_ERROR_SEEK;
  816|      0|        goto cleanup;
  817|      0|    }
  818|       |
  819|  2.81k|    if (io->seek(0, READSTAT_SEEK_SET, io->io_ctx) == -1) {
  ------------------
  |  Branch (819:9): [True: 0, False: 2.81k]
  ------------------
  820|      0|        retval = READSTAT_ERROR_SEEK;
  821|      0|        goto cleanup;
  822|      0|    }
  823|       |    
  824|  2.81k|    if (read_bytes(ctx, vanity, sizeof(vanity)) != sizeof(vanity)) {
  ------------------
  |  Branch (824:9): [True: 60, False: 2.75k]
  ------------------
  825|     60|        retval = READSTAT_ERROR_READ;
  826|     60|        goto cleanup;
  827|     60|    }
  828|       |
  829|  2.75k|    retval = readstat_convert(ctx->file_label, sizeof(ctx->file_label), vanity[1] + 20, 20, NULL);
  830|  2.75k|    if (retval != READSTAT_OK)
  ------------------
  |  Branch (830:9): [True: 0, False: 2.75k]
  ------------------
  831|      0|        goto cleanup;
  832|       |    
  833|  2.75k|    if (read_bytes(ctx, reverse_lookup, sizeof(reverse_lookup)) != sizeof(reverse_lookup)) {
  ------------------
  |  Branch (833:9): [True: 90, False: 2.66k]
  ------------------
  834|     90|        retval = READSTAT_ERROR_READ;
  835|     90|        goto cleanup;
  836|     90|    }
  837|       |    
  838|  2.66k|    ctx->space = reverse_lookup[126];
  839|       |
  840|  2.66k|    int i;
  841|       |
  842|       |    /* A byte that appears at several positions in the translation table
  843|       |     * keeps its first meaning, as in PSPP and R's foreign package. PSPP for
  844|       |     * instance maps the superscript digits (positions 167-176) to '0'-'9'
  845|       |     * as well, and last-writer-wins would turn every digit into a
  846|       |     * superscript. */
  847|   683k|    for (i=0; i<256; i++) {
  ------------------
  |  Branch (847:15): [True: 681k, False: 2.66k]
  ------------------
  848|   681k|        if (ctx->byte2unicode[reverse_lookup[i]])
  ------------------
  |  Branch (848:13): [True: 335k, False: 346k]
  ------------------
  849|   335k|            continue;
  850|   346k|        if (por_ascii_lookup[i]) {
  ------------------
  |  Branch (850:13): [True: 107k, False: 238k]
  ------------------
  851|   107k|            ctx->byte2unicode[reverse_lookup[i]] = por_ascii_lookup[i];
  852|   238k|        } else if (por_unicode_lookup[i]) {
  ------------------
  |  Branch (852:20): [True: 535, False: 238k]
  ------------------
  853|    535|            ctx->byte2unicode[reverse_lookup[i]] = por_unicode_lookup[i];
  854|    535|        }
  855|   346k|    }
  856|       |
  857|  2.66k|    ctx->byte2unicode[reverse_lookup[64]] = por_unicode_lookup[64];
  858|       |
  859|  2.66k|    unsigned char check[8];
  860|  2.66k|    char tr_check[8];
  861|       |    
  862|  2.66k|    if (read_bytes(ctx, check, sizeof(check)) != sizeof(check)) {
  ------------------
  |  Branch (862:9): [True: 29, False: 2.63k]
  ------------------
  863|     29|        retval = READSTAT_ERROR_READ;
  864|     29|        goto cleanup;
  865|     29|    }
  866|       |
  867|  2.63k|    ssize_t encoded_len;
  868|       |
  869|  2.63k|    if ((encoded_len = por_utf8_encode(check, sizeof(check), tr_check, sizeof(tr_check), ctx->byte2unicode)) == -1) {
  ------------------
  |  Branch (869:9): [True: 0, False: 2.63k]
  ------------------
  870|      0|        if (ctx->handle.error) {
  ------------------
  |  Branch (870:13): [True: 0, False: 0]
  ------------------
  871|      0|            snprintf(error_buf, sizeof(error_buf), "Error converting check string: %.*s", (int)sizeof(check), check);
  872|      0|            ctx->handle.error(error_buf, ctx->user_ctx);
  873|      0|        }
  874|      0|        retval = READSTAT_ERROR_CONVERT;
  875|      0|        goto cleanup;
  876|      0|    }
  877|       |
  878|  2.63k|    if (strncmp("SPSSPORT", tr_check, encoded_len) != 0) {
  ------------------
  |  Branch (878:9): [True: 143, False: 2.48k]
  ------------------
  879|    143|        retval = READSTAT_ERROR_PARSE;
  880|    143|        goto cleanup;
  881|    143|    }
  882|       |    
  883|  2.48k|    ctx->var_offset = -1;
  884|       |    
  885|  2.48k|    char string[256];
  886|       |
  887|  2.48k|    retval = read_version_and_timestamp(ctx);
  888|  2.48k|    if (retval != READSTAT_OK)
  ------------------
  |  Branch (888:9): [True: 738, False: 1.75k]
  ------------------
  889|    738|        goto cleanup;
  890|       |
  891|  33.5k|    while (1) {
  ------------------
  |  Branch (891:12): [True: 33.5k, Folded]
  ------------------
  892|  33.5k|        uint16_t tr_tag = read_tag(ctx);
  893|  33.5k|        switch (tr_tag) {
  894|    457|            case '1': /* product ID */
  ------------------
  |  Branch (894:13): [True: 457, False: 33.1k]
  ------------------
  895|    726|            case '2': /* author ID */
  ------------------
  |  Branch (895:13): [True: 269, False: 33.2k]
  ------------------
  896|  1.04k|            case '3': /* sub-product ID */
  ------------------
  |  Branch (896:13): [True: 321, False: 33.2k]
  ------------------
  897|  1.04k|                retval = read_string(ctx, string, sizeof(string));
  898|  1.04k|                break;
  899|  1.19k|            case '4': /* variable count */
  ------------------
  |  Branch (899:13): [True: 1.19k, False: 32.3k]
  ------------------
  900|  1.19k|                retval = read_variable_count_record(ctx);
  901|  1.19k|                break;
  902|    463|            case '5': /* precision */
  ------------------
  |  Branch (902:13): [True: 463, False: 33.1k]
  ------------------
  903|    463|                retval = read_precision_record(ctx);
  904|    463|                break;
  905|  1.25k|            case '6': /* case weight */
  ------------------
  |  Branch (905:13): [True: 1.25k, False: 32.3k]
  ------------------
  906|  1.25k|                retval = read_case_weight_record(ctx);
  907|  1.25k|                break;
  908|  9.51k|            case '7': /* variable */
  ------------------
  |  Branch (908:13): [True: 9.51k, False: 24.0k]
  ------------------
  909|  9.51k|                retval = read_variable_record(ctx);
  910|  9.51k|                break;
  911|    887|            case '8': /* missing value */
  ------------------
  |  Branch (911:13): [True: 887, False: 32.6k]
  ------------------
  912|    887|                retval = read_missing_value_record(ctx);
  913|    887|                break;
  914|  6.67k|            case 'B': /* missing value range */
  ------------------
  |  Branch (914:13): [True: 6.67k, False: 26.8k]
  ------------------
  915|  6.67k|                retval = read_missing_value_range_record(ctx);
  916|  6.67k|                break;
  917|  1.81k|            case '9': /* LO THRU x */
  ------------------
  |  Branch (917:13): [True: 1.81k, False: 31.7k]
  ------------------
  918|  1.81k|                retval = read_missing_value_lo_range_record(ctx);
  919|  1.81k|                break;
  920|  2.57k|            case 'A': /* x THRU HI */
  ------------------
  |  Branch (920:13): [True: 2.57k, False: 30.9k]
  ------------------
  921|  2.57k|                retval = read_missing_value_hi_range_record(ctx);
  922|  2.57k|                break;
  923|  1.17k|            case 'C': /* variable label */
  ------------------
  |  Branch (923:13): [True: 1.17k, False: 32.3k]
  ------------------
  924|  1.17k|                retval = read_variable_label_record(ctx);
  925|  1.17k|                break;
  926|  5.49k|            case 'D': /* value label */
  ------------------
  |  Branch (926:13): [True: 5.49k, False: 28.0k]
  ------------------
  927|  5.49k|                retval = read_value_label_record(ctx);
  928|  5.49k|                break;
  929|    750|            case 'E': /* document record */
  ------------------
  |  Branch (929:13): [True: 750, False: 32.8k]
  ------------------
  930|    750|                retval = read_document_record(ctx);
  931|    750|                break;
  932|    411|            case 'F': /* file data */
  ------------------
  |  Branch (932:13): [True: 411, False: 33.1k]
  ------------------
  933|    411|                if (ctx->var_offset != ctx->var_count - 1) {
  ------------------
  |  Branch (933:21): [True: 31, False: 380]
  ------------------
  934|     31|                    retval = READSTAT_ERROR_COLUMN_COUNT_MISMATCH;
  935|     31|                    goto cleanup;
  936|     31|                }
  937|       |
  938|    380|                retval = handle_variables(ctx);
  939|    380|                if (retval != READSTAT_OK)
  ------------------
  |  Branch (939:21): [True: 0, False: 380]
  ------------------
  940|      0|                    goto cleanup;
  941|       |
  942|    380|                if (ctx->handle.value) {
  ------------------
  |  Branch (942:21): [True: 380, False: 0]
  ------------------
  943|    380|                    retval = read_por_file_data(ctx);
  944|    380|                }
  945|    380|                goto cleanup;
  946|    318|            default:
  ------------------
  |  Branch (946:13): [True: 318, False: 33.2k]
  ------------------
  947|    318|                retval = READSTAT_ERROR_PARSE;
  948|    318|                goto cleanup;
  949|  33.5k|        }
  950|  32.8k|        if (retval != READSTAT_OK)
  ------------------
  |  Branch (950:13): [True: 1.02k, False: 31.8k]
  ------------------
  951|  1.02k|            break;
  952|  32.8k|    }
  953|       |
  954|  2.81k|cleanup:
  955|  2.81k|    io->close(io->io_ctx);
  956|  2.81k|    por_ctx_free(ctx);
  957|       |    
  958|  2.81k|    return retval;
  959|  1.75k|}
readstat_por_read.c:read_bytes:
   49|  2.33M|static ssize_t read_bytes(por_ctx_t *ctx, void *dst, size_t len) {
   50|  2.33M|    char *dst_pos = (char *)dst;
   51|  2.33M|    readstat_io_t *io = ctx->io;
   52|  2.33M|    char byte;
   53|       |
   54|  6.90M|    while (dst_pos < (char *)dst + len) {
  ------------------
  |  Branch (54:12): [True: 4.57M, False: 2.33M]
  ------------------
   55|  4.57M|        if (ctx->num_spaces) {
  ------------------
  |  Branch (55:13): [True: 2.81M, False: 1.75M]
  ------------------
   56|  2.81M|            *dst_pos++ = ctx->space;
   57|  2.81M|            ctx->num_spaces--;
   58|  2.81M|            continue;
   59|  2.81M|        }
   60|  1.75M|        ssize_t bytes_read = io->read(&byte, 1, io->io_ctx);
   61|  1.75M|        if (bytes_read == 0) {
  ------------------
  |  Branch (61:13): [True: 1.87k, False: 1.75M]
  ------------------
   62|  1.87k|            break;
   63|  1.87k|        }
   64|  1.75M|        if (bytes_read == -1) {
  ------------------
  |  Branch (64:13): [True: 0, False: 1.75M]
  ------------------
   65|      0|            return -1;
   66|      0|        }
   67|       |        /* Like PSPP: ignore carriage returns entirely; a line feed ends the
   68|       |         * line, and a line shorter than 80 characters is padded with spaces.
   69|       |         * Lines longer than 80 characters are read as-is. */
   70|  1.75M|        if (byte == '\r') {
  ------------------
  |  Branch (70:13): [True: 2.75k, False: 1.75M]
  ------------------
   71|  2.75k|            continue;
   72|  1.75M|        } else if (byte == '\n') {
  ------------------
  |  Branch (72:20): [True: 44.6k, False: 1.70M]
  ------------------
   73|  44.6k|            if (ctx->pos < POR_LINE_LENGTH)
  ------------------
  |  |   24|  44.6k|#define POR_LINE_LENGTH         80
  ------------------
  |  Branch (73:17): [True: 43.0k, False: 1.57k]
  ------------------
   74|  43.0k|                ctx->num_spaces = POR_LINE_LENGTH - ctx->pos;
  ------------------
  |  |   24|  43.0k|#define POR_LINE_LENGTH         80
  ------------------
   75|  44.6k|            ctx->pos = 0;
   76|  44.6k|            continue;
   77|  44.6k|        }
   78|  1.70M|        *dst_pos++ = byte;
   79|  1.70M|        ctx->pos++;
   80|  1.70M|    }
   81|       |    
   82|  2.33M|    return (int)(dst_pos - (char *)dst);
   83|  2.33M|}
readstat_por_read.c:read_string:
  248|  39.0k|static readstat_error_t read_string(por_ctx_t *ctx, char *data, size_t len) {
  249|  39.0k|    int finished = 0;
  250|  39.0k|    readstat_error_t retval = maybe_read_string(ctx, data, len, &finished);
  251|  39.0k|    if (retval == READSTAT_OK && finished) {
  ------------------
  |  Branch (251:9): [True: 38.0k, False: 1.04k]
  |  Branch (251:34): [True: 8, False: 37.9k]
  ------------------
  252|      8|        return READSTAT_ERROR_PARSE;
  253|      8|    }
  254|  39.0k|    return retval;
  255|  39.0k|}
readstat_por_read.c:maybe_read_string:
  196|  39.4k|static readstat_error_t maybe_read_string(por_ctx_t *ctx, char *data, size_t len, int *out_finished) {
  197|  39.4k|    readstat_error_t retval = READSTAT_OK;
  198|  39.4k|    double value;
  199|  39.4k|    int finished = 0;
  200|  39.4k|    char error_buf[1024];
  201|  39.4k|    size_t string_length = 0;
  202|  39.4k|    retval = maybe_read_double(ctx, &value, &finished);
  203|  39.4k|    if (retval != READSTAT_OK || finished) {
  ------------------
  |  Branch (203:9): [True: 844, False: 38.6k]
  |  Branch (203:34): [True: 11, False: 38.6k]
  ------------------
  204|    855|        if (out_finished)
  ------------------
  |  Branch (204:13): [True: 855, False: 0]
  ------------------
  205|    855|            *out_finished = finished;
  206|       |
  207|    855|        return retval;
  208|    855|    }
  209|       |    
  210|  38.6k|    if (value < 0 || value > MAX_STRING_LENGTH || isnan(value)) {
  ------------------
  |  |   31|  77.2k|#define MAX_STRING_LENGTH   20000
  ------------------
  |  Branch (210:9): [True: 1, False: 38.6k]
  |  Branch (210:22): [True: 258, False: 38.3k]
  |  Branch (210:51): [True: 2, False: 38.3k]
  ------------------
  211|    261|        retval = READSTAT_ERROR_PARSE;
  212|    261|        goto cleanup;
  213|    261|    }
  214|  38.3k|    string_length = (size_t)value;
  215|       |    
  216|  38.3k|    if (string_length > ctx->string_buffer_len) {
  ------------------
  |  Branch (216:9): [True: 2.39k, False: 35.9k]
  ------------------
  217|  2.39k|        unsigned char *new_string_buf = realloc(ctx->string_buffer, string_length);
  218|  2.39k|        if (new_string_buf == NULL) { retval = READSTAT_ERROR_MALLOC; goto cleanup; }
  ------------------
  |  Branch (218:13): [True: 0, False: 2.39k]
  ------------------
  219|  2.39k|        ctx->string_buffer = new_string_buf;
  220|  2.39k|        ctx->string_buffer_len = string_length;
  221|  2.39k|        memset(ctx->string_buffer, 0, ctx->string_buffer_len);
  222|  2.39k|    }
  223|       |    
  224|  38.3k|    if (read_bytes(ctx, ctx->string_buffer, string_length) != string_length) {
  ------------------
  |  Branch (224:9): [True: 108, False: 38.2k]
  ------------------
  225|    108|        retval = READSTAT_ERROR_READ;
  226|    108|        goto cleanup;
  227|    108|    }
  228|  38.2k|    size_t bytes_encoded = por_utf8_encode(ctx->string_buffer, string_length, 
  229|  38.2k|            data, len - 1, ctx->byte2unicode);
  230|  38.2k|    if (bytes_encoded == -1) {
  ------------------
  |  Branch (230:9): [True: 0, False: 38.2k]
  ------------------
  231|      0|        if (ctx->handle.error) {
  ------------------
  |  Branch (231:13): [True: 0, False: 0]
  ------------------
  232|      0|            snprintf(error_buf, sizeof(error_buf), "Error converting string: %.*s", 
  233|      0|                    (int)string_length, ctx->string_buffer);
  234|      0|            ctx->handle.error(error_buf, ctx->user_ctx);
  235|      0|        }
  236|      0|        retval = READSTAT_ERROR_CONVERT;
  237|      0|        goto cleanup;
  238|      0|    }
  239|       |    
  240|  38.2k|    data[bytes_encoded] = '\0';
  241|  38.2k|    if (out_finished)
  ------------------
  |  Branch (241:9): [True: 38.2k, False: 0]
  ------------------
  242|  38.2k|        *out_finished = 0;
  243|       |
  244|  38.6k|cleanup:
  245|  38.6k|    return retval;
  246|  38.2k|}
readstat_por_read.c:maybe_read_double:
  176|  53.8k|static readstat_error_t maybe_read_double(por_ctx_t *ctx, double *out_double, int *out_finished) {
  177|  53.8k|    unsigned char peek;
  178|  53.8k|    size_t bytes_read = read_bytes(ctx, &peek, 1);
  179|  53.8k|    if (bytes_read != 1)
  ------------------
  |  Branch (179:9): [True: 611, False: 53.2k]
  ------------------
  180|    611|        return READSTAT_ERROR_PARSE;
  181|       |
  182|  53.2k|    if (ctx->byte2unicode[peek] == 'Z') {
  ------------------
  |  Branch (182:9): [True: 14, False: 53.1k]
  ------------------
  183|     14|        if (out_double)
  ------------------
  |  Branch (183:13): [True: 14, False: 0]
  ------------------
  184|     14|            *out_double = NAN;
  185|     14|        if (out_finished)
  ------------------
  |  Branch (185:13): [True: 14, False: 0]
  ------------------
  186|     14|            *out_finished = 1;
  187|     14|        return READSTAT_OK;
  188|     14|    }
  189|       |
  190|  53.1k|    if (out_finished)
  ------------------
  |  Branch (190:9): [True: 53.1k, False: 0]
  ------------------
  191|  53.1k|        *out_finished = 0;
  192|       |
  193|  53.1k|    return read_double_with_peek(ctx, out_double, peek);
  194|  53.2k|}
readstat_por_read.c:read_double_with_peek:
   94|   159k|        unsigned char peek) {
   95|   159k|    readstat_error_t retval = READSTAT_OK;
   96|   159k|    double value = NAN;
   97|   159k|    unsigned char buffer[100];
   98|   159k|    char utf8_buffer[300];
   99|   159k|    char error_buf[1024];
  100|   159k|    int64_t len = 0;
  101|   159k|    ssize_t bytes_read = 0;
  102|       |
  103|   159k|    buffer[0] = peek;
  104|       |
  105|   159k|    bytes_read = read_bytes(ctx, &buffer[1], 1);
  106|   159k|    if (bytes_read != 1)
  ------------------
  |  Branch (106:9): [True: 97, False: 159k]
  ------------------
  107|     97|        return READSTAT_ERROR_PARSE;
  108|       |
  109|   159k|    if (ctx->byte2unicode[buffer[0]] == '*' && 
  ------------------
  |  Branch (109:9): [True: 264, False: 158k]
  ------------------
  110|    264|            ctx->byte2unicode[buffer[1]] == '.') {
  ------------------
  |  Branch (110:13): [True: 262, False: 2]
  ------------------
  111|    262|        if (out_double)
  ------------------
  |  Branch (111:13): [True: 262, False: 0]
  ------------------
  112|    262|            *out_double = NAN;
  113|    262|        return READSTAT_OK;
  114|    262|    }
  115|   158k|    int64_t i=2;
  116|  2.08M|    while (i<sizeof(buffer) && ctx->byte2unicode[buffer[i-1]] != '/') {
  ------------------
  |  Branch (116:12): [True: 2.08M, False: 16]
  |  Branch (116:32): [True: 1.93M, False: 158k]
  ------------------
  117|  1.93M|        bytes_read = read_bytes(ctx, &buffer[i], 1);
  118|  1.93M|        if (bytes_read != 1)
  ------------------
  |  Branch (118:13): [True: 363, False: 1.93M]
  ------------------
  119|    363|            return READSTAT_ERROR_PARSE;
  120|  1.93M|        i++;
  121|  1.93M|    }
  122|       |
  123|   158k|    if (i == sizeof(buffer)) {
  ------------------
  |  Branch (123:9): [True: 16, False: 158k]
  ------------------
  124|     16|        return READSTAT_ERROR_PARSE;
  125|     16|    }
  126|       |
  127|   158k|    len = por_utf8_encode(buffer, i, utf8_buffer, sizeof(utf8_buffer), ctx->byte2unicode);
  128|   158k|    if (len == -1) {
  ------------------
  |  Branch (128:9): [True: 0, False: 158k]
  ------------------
  129|      0|        if (ctx->handle.error) {
  ------------------
  |  Branch (129:13): [True: 0, False: 0]
  ------------------
  130|      0|            snprintf(error_buf, sizeof(error_buf), "Error converting double string (length=%" PRId64 "): %.*s", 
  131|      0|                    i, (int)i, buffer);
  132|      0|            ctx->handle.error(error_buf, ctx->user_ctx);
  133|      0|        }
  134|      0|        retval = READSTAT_ERROR_CONVERT;
  135|      0|        goto cleanup;
  136|      0|    }
  137|       |    
  138|   158k|    bytes_read = readstat_por_parse_double(utf8_buffer, len, &value, ctx->handle.error, ctx->user_ctx);
  139|   158k|    if (bytes_read == -1) {
  ------------------
  |  Branch (139:9): [True: 96, False: 158k]
  ------------------
  140|     96|        if (ctx->handle.error) {
  ------------------
  |  Branch (140:13): [True: 0, False: 96]
  ------------------
  141|      0|            snprintf(error_buf, sizeof(error_buf), "Error parsing double string (length=%" PRId64 "): %.*s [%s]", 
  142|      0|                    len, (int)len, utf8_buffer, buffer);
  143|      0|            ctx->handle.error(error_buf, ctx->user_ctx);
  144|      0|        }
  145|     96|        retval = READSTAT_ERROR_PARSE;
  146|     96|        goto cleanup;
  147|     96|    }
  148|       |    
  149|   158k|cleanup:
  150|   158k|    if (out_double)
  ------------------
  |  Branch (150:9): [True: 158k, False: 0]
  ------------------
  151|   158k|        *out_double = value;
  152|       |
  153|   158k|    return retval;
  154|   158k|}
readstat_por_read.c:read_tag:
   85|  33.5k|static uint16_t read_tag(por_ctx_t *ctx) {
   86|  33.5k|    unsigned char tag;
   87|  33.5k|    if (read_bytes(ctx, &tag, 1) != 1) {
  ------------------
  |  Branch (87:9): [True: 224, False: 33.3k]
  ------------------
   88|    224|        return -1;
   89|    224|    }
   90|  33.3k|    return ctx->byte2unicode[tag];
   91|  33.5k|}
readstat_por_read.c:read_variable_count_record:
  257|  1.19k|static readstat_error_t read_variable_count_record(por_ctx_t *ctx) {
  258|  1.19k|    int value;
  259|  1.19k|    readstat_error_t retval = READSTAT_OK;
  260|  1.19k|    if (ctx->var_count) {
  ------------------
  |  Branch (260:9): [True: 15, False: 1.18k]
  ------------------
  261|     15|        retval = READSTAT_ERROR_PARSE;
  262|     15|        goto cleanup;
  263|     15|    }
  264|  1.18k|    if ((retval = read_integer_in_range(ctx, 0, MAX_VARS, &value)) != READSTAT_OK) {
  ------------------
  |  |   35|  1.18k|#define MAX_VARS    1000000
  ------------------
  |  Branch (264:9): [True: 17, False: 1.16k]
  ------------------
  265|     17|        goto cleanup;
  266|     17|    }
  267|  1.16k|    ctx->var_count = value;
  268|  1.16k|    ctx->variables = readstat_calloc(ctx->var_count, sizeof(readstat_variable_t *));
  269|  1.16k|    ctx->varinfo = readstat_calloc(ctx->var_count, sizeof(spss_varinfo_t));
  270|  1.16k|    if (ctx->variables == NULL || ctx->varinfo == NULL) {
  ------------------
  |  Branch (270:9): [True: 2, False: 1.16k]
  |  Branch (270:35): [True: 6, False: 1.15k]
  ------------------
  271|      8|        retval = READSTAT_ERROR_MALLOC;
  272|      8|        goto cleanup;
  273|      8|    }
  274|       |
  275|  1.15k|    if (ctx->handle.metadata) {
  ------------------
  |  Branch (275:9): [True: 1.15k, False: 0]
  ------------------
  276|  1.15k|        readstat_metadata_t metadata = {
  277|  1.15k|            .row_count = -1,
  278|  1.15k|            .var_count = ctx->var_count,
  279|  1.15k|            .creation_time = ctx->timestamp,
  280|  1.15k|            .modified_time = ctx->timestamp,
  281|  1.15k|            .file_format_version = ctx->version,
  282|  1.15k|            .file_label = ctx->file_label
  283|  1.15k|        };
  284|  1.15k|        if (ctx->handle.metadata(&metadata, ctx->user_ctx) != READSTAT_HANDLER_OK) {
  ------------------
  |  |   22|  1.15k|#define READSTAT_HANDLER_OK             0
  ------------------
  |  Branch (284:13): [True: 0, False: 1.15k]
  ------------------
  285|      0|            retval = READSTAT_ERROR_USER_ABORT;
  286|      0|            goto cleanup;
  287|      0|        }
  288|  1.15k|    }
  289|       |        
  290|  1.19k|cleanup:
  291|  1.19k|    return retval;
  292|  1.15k|}
readstat_por_read.c:read_integer_in_range:
  164|  78.6k|static readstat_error_t read_integer_in_range(por_ctx_t *ctx, int min, int max, int *out_integer) {
  165|  78.6k|    double dval = NAN;
  166|  78.6k|    readstat_error_t retval = read_double(ctx, &dval);
  167|  78.6k|    if (retval != READSTAT_OK)
  ------------------
  |  Branch (167:9): [True: 288, False: 78.3k]
  ------------------
  168|    288|        return retval;
  169|  78.3k|    if (isnan(dval) || dval < min || dval > max)
  ------------------
  |  Branch (169:9): [True: 11, False: 78.3k]
  |  Branch (169:24): [True: 9, False: 78.2k]
  |  Branch (169:38): [True: 14, False: 78.2k]
  ------------------
  170|     34|        return READSTAT_ERROR_PARSE;
  171|  78.2k|    if (out_integer)
  ------------------
  |  Branch (171:9): [True: 78.2k, False: 0]
  ------------------
  172|  78.2k|        *out_integer = (int)dval;
  173|  78.2k|    return READSTAT_OK;
  174|  78.3k|}
readstat_por_read.c:read_double:
  156|   106k|static readstat_error_t read_double(por_ctx_t *ctx, double *out_double) {
  157|   106k|    unsigned char peek;
  158|   106k|    size_t bytes_read = read_bytes(ctx, &peek, 1);
  159|   106k|    if (bytes_read != 1)
  ------------------
  |  Branch (159:9): [True: 279, False: 106k]
  ------------------
  160|    279|        return READSTAT_ERROR_PARSE;
  161|   106k|    return read_double_with_peek(ctx, out_double, peek);
  162|   106k|}
readstat_por_read.c:read_precision_record:
  294|    463|static readstat_error_t read_precision_record(por_ctx_t *ctx) {
  295|    463|    int precision = 0;
  296|    463|    readstat_error_t error = read_integer_in_range(ctx, 0, 100, &precision);
  297|    463|    if (error == READSTAT_OK)
  ------------------
  |  Branch (297:9): [True: 446, False: 17]
  ------------------
  298|    446|        ctx->base30_precision = precision;
  299|    463|    return error;
  300|    463|}
readstat_por_read.c:read_case_weight_record:
  302|  1.25k|static readstat_error_t read_case_weight_record(por_ctx_t *ctx) {
  303|  1.25k|    return read_string(ctx, ctx->fweight_name, sizeof(ctx->fweight_name));
  304|  1.25k|}
readstat_por_read.c:read_variable_record:
  306|  9.51k|static readstat_error_t read_variable_record(por_ctx_t *ctx) {
  307|  9.51k|    readstat_error_t retval = READSTAT_OK;
  308|  9.51k|    int value;
  309|  9.51k|    int i;
  310|  9.51k|    spss_varinfo_t *varinfo = NULL;
  311|  9.51k|    spss_format_t *formats[2];
  312|       |
  313|  9.51k|    ctx->var_offset++;
  314|       |
  315|  9.51k|    if (ctx->var_offset == ctx->var_count) {
  ------------------
  |  Branch (315:9): [True: 2, False: 9.50k]
  ------------------
  316|      2|        retval = READSTAT_ERROR_PARSE;
  317|      2|        goto cleanup;
  318|      2|    }
  319|       |
  320|  9.50k|    varinfo = &ctx->varinfo[ctx->var_offset];
  321|  9.50k|    formats[0] = &varinfo->print_format;
  322|  9.50k|    formats[1] = &varinfo->write_format;
  323|       |
  324|  9.50k|    varinfo->labels_index = -1;
  325|  9.50k|    if ((retval = read_integer_in_range(ctx, 0, MAX_WIDTH, &value)) != READSTAT_OK) {
  ------------------
  |  |   36|  9.50k|#define MAX_WIDTH   1000000
  ------------------
  |  Branch (325:9): [True: 24, False: 9.48k]
  ------------------
  326|     24|        goto cleanup;
  327|     24|    }
  328|  9.48k|    varinfo->width = value;
  329|  9.48k|    if (varinfo->width == 0) {
  ------------------
  |  Branch (329:9): [True: 4.38k, False: 5.09k]
  ------------------
  330|  4.38k|        varinfo->type = READSTAT_TYPE_DOUBLE;
  331|  4.38k|        varinfo->width = 1; /* one eight-byte slot, as in SAV files */
  332|  5.09k|    } else {
  333|  5.09k|        varinfo->type = READSTAT_TYPE_STRING;
  334|       |        /* The declared width is the string length in characters */
  335|  5.09k|        varinfo->string_length = value;
  336|  5.09k|    }
  337|  9.48k|    if ((retval = read_string(ctx, varinfo->name, sizeof(varinfo->name))) != READSTAT_OK) {
  ------------------
  |  Branch (337:9): [True: 36, False: 9.44k]
  ------------------
  338|     36|        goto cleanup;
  339|     36|    }
  340|  9.44k|    ck_str_hash_insert(varinfo->name, varinfo, ctx->var_dict);
  341|       |
  342|  28.0k|    for (i=0; i<sizeof(formats)/sizeof(spss_format_t *); i++) {
  ------------------
  |  Branch (342:15): [True: 18.7k, False: 9.26k]
  ------------------
  343|  18.7k|        spss_format_t *format = formats[i];
  344|  18.7k|        if ((retval = read_integer_in_range(ctx, 0, MAX_FORMAT_TYPE, &value)) != READSTAT_OK) {
  ------------------
  |  |   28|  18.7k|#define MAX_FORMAT_TYPE     (POR_FORMAT_SHIFT+SPSS_FORMAT_TYPE_YMDHMS)
  |  |  ------------------
  |  |  |  |   27|  18.7k|#define POR_FORMAT_SHIFT     82
  |  |  ------------------
  |  |               #define MAX_FORMAT_TYPE     (POR_FORMAT_SHIFT+SPSS_FORMAT_TYPE_YMDHMS)
  |  |  ------------------
  |  |  |  |   38|  18.7k|#define SPSS_FORMAT_TYPE_YMDHMS   41
  |  |  ------------------
  ------------------
  |  Branch (344:13): [True: 134, False: 18.6k]
  ------------------
  345|    134|            goto cleanup;
  346|    134|        }
  347|  18.6k|        if (value > POR_FORMAT_SHIFT) {
  ------------------
  |  |   27|  18.6k|#define POR_FORMAT_SHIFT     82
  ------------------
  |  Branch (347:13): [True: 659, False: 17.9k]
  ------------------
  348|       |            // Some files in the wild have their format types shifted by 82 for date/time values
  349|       |            // I have no idea why, but see test files linked from:
  350|       |            // https://github.com/WizardMac/ReadStat/issues/158
  351|    659|            format->type = value - POR_FORMAT_SHIFT;
  ------------------
  |  |   27|    659|#define POR_FORMAT_SHIFT     82
  ------------------
  352|  17.9k|        } else {
  353|  17.9k|            format->type = value;
  354|  17.9k|        }
  355|       |
  356|  18.6k|        if ((retval = read_integer_in_range(ctx, 0, MAX_FORMAT_WIDTH, &value)) != READSTAT_OK) {
  ------------------
  |  |   29|  18.6k|#define MAX_FORMAT_WIDTH    20000
  ------------------
  |  Branch (356:13): [True: 33, False: 18.5k]
  ------------------
  357|     33|            goto cleanup;
  358|     33|        }
  359|  18.5k|        format->width = value;
  360|       |
  361|  18.5k|        if ((retval = read_integer_in_range(ctx, 0, MAX_FORMAT_DECIMALS, &value)) != READSTAT_OK) {
  ------------------
  |  |   30|  18.5k|#define MAX_FORMAT_DECIMALS   100
  ------------------
  |  Branch (361:13): [True: 16, False: 18.5k]
  ------------------
  362|     16|            goto cleanup;
  363|     16|        }
  364|  18.5k|        format->decimal_places = value;
  365|  18.5k|    }
  366|       |
  367|  9.51k|cleanup:
  368|  9.51k|    return retval;
  369|  9.44k|}
readstat_por_read.c:read_missing_value_record:
  402|    887|static readstat_error_t read_missing_value_record(por_ctx_t *ctx) {
  403|    887|    readstat_error_t retval = READSTAT_OK;
  404|    887|    spss_varinfo_t *varinfo = NULL;
  405|       |
  406|    887|    if (ctx->var_offset < 0 || ctx->var_offset >= ctx->var_count) {
  ------------------
  |  Branch (406:9): [True: 2, False: 885]
  |  Branch (406:32): [True: 0, False: 885]
  ------------------
  407|      2|        retval = READSTAT_ERROR_PARSE;
  408|      2|        goto cleanup;
  409|      2|    }
  410|    885|    varinfo = &ctx->varinfo[ctx->var_offset];
  411|       |
  412|    885|    if (varinfo->n_missing_values >= 3) {
  ------------------
  |  Branch (412:9): [True: 5, False: 880]
  ------------------
  413|      5|        retval = READSTAT_ERROR_PARSE;
  414|      5|        goto cleanup;
  415|      5|    }
  416|    880|    if (varinfo->type == READSTAT_TYPE_DOUBLE) {
  ------------------
  |  Branch (416:9): [True: 573, False: 307]
  ------------------
  417|    573|        if ((retval = read_double(ctx, &varinfo->missing_double_values[varinfo->n_missing_values])) != READSTAT_OK) {
  ------------------
  |  Branch (417:13): [True: 16, False: 557]
  ------------------
  418|     16|            goto cleanup;
  419|     16|        }
  420|    573|    } else {
  421|    307|        if ((retval = read_missing_string_value(ctx, varinfo, varinfo->n_missing_values)) != READSTAT_OK) {
  ------------------
  |  Branch (421:13): [True: 12, False: 295]
  ------------------
  422|     12|            goto cleanup;
  423|     12|        }
  424|    307|    }
  425|    852|    varinfo->n_missing_values++;
  426|       |
  427|    887|cleanup:
  428|    887|    return retval;
  429|    852|}
readstat_por_read.c:read_missing_string_value:
  397|  2.68k|static readstat_error_t read_missing_string_value(por_ctx_t *ctx, spss_varinfo_t *varinfo, int index) {
  398|  2.68k|    return read_converted_string(ctx, varinfo->missing_string_values[index],
  399|  2.68k|            sizeof(varinfo->missing_string_values[index]));
  400|  2.68k|}
readstat_por_read.c:read_converted_string:
  375|  16.6k|static readstat_error_t read_converted_string(por_ctx_t *ctx, char *dst, size_t dst_len) {
  376|  16.6k|    readstat_error_t retval = READSTAT_OK;
  377|  16.6k|    char string[POR_STRING_BUFFER_SIZE];
  378|  16.6k|    size_t len = 0;
  379|       |
  380|  16.6k|    if ((retval = read_string(ctx, string, sizeof(string))) != READSTAT_OK)
  ------------------
  |  Branch (380:9): [True: 209, False: 16.4k]
  ------------------
  381|    209|        goto cleanup;
  382|       |
  383|  16.4k|    len = strlen(string);
  384|  17.1k|    while (len > 0 && string[len-1] == ' ')
  ------------------
  |  Branch (384:12): [True: 12.9k, False: 4.20k]
  |  Branch (384:23): [True: 763, False: 12.2k]
  ------------------
  385|    763|        len--;
  386|  16.4k|    if (len + 1 > dst_len) {
  ------------------
  |  Branch (386:9): [True: 937, False: 15.4k]
  ------------------
  387|    937|        len = dst_len - 1;
  388|  1.28k|        while (len > 0 && (string[len] & 0xC0) == 0x80)
  ------------------
  |  Branch (388:16): [True: 1.28k, False: 0]
  |  Branch (388:27): [True: 349, False: 937]
  ------------------
  389|    349|            len--;
  390|    937|    }
  391|  16.4k|    retval = readstat_convert(dst, dst_len, string, len, ctx->converter);
  392|       |
  393|  16.6k|cleanup:
  394|  16.6k|    return retval;
  395|  16.4k|}
readstat_por_read.c:read_missing_value_range_record:
  431|  6.67k|static readstat_error_t read_missing_value_range_record(por_ctx_t *ctx) {
  432|  6.67k|    readstat_error_t retval = READSTAT_OK;
  433|  6.67k|    spss_varinfo_t *varinfo = NULL;
  434|       |
  435|  6.67k|    if (ctx->var_offset < 0 || ctx->var_offset == ctx->var_count) {
  ------------------
  |  Branch (435:9): [True: 2, False: 6.67k]
  |  Branch (435:32): [True: 0, False: 6.67k]
  ------------------
  436|      2|        retval = READSTAT_ERROR_PARSE;
  437|      2|        goto cleanup;
  438|      2|    }
  439|  6.67k|    varinfo = &ctx->varinfo[ctx->var_offset];
  440|       |
  441|  6.67k|    varinfo->missing_range = 1;
  442|  6.67k|    varinfo->n_missing_values = 2;
  443|  6.67k|    if (varinfo->type == READSTAT_TYPE_DOUBLE) {
  ------------------
  |  Branch (443:9): [True: 6.11k, False: 558]
  ------------------
  444|  6.11k|        if ((retval = read_double(ctx, &varinfo->missing_double_values[0])) != READSTAT_OK) {
  ------------------
  |  Branch (444:13): [True: 19, False: 6.09k]
  ------------------
  445|     19|            goto cleanup;
  446|     19|        }
  447|  6.09k|        if ((retval = read_double(ctx, &varinfo->missing_double_values[1])) != READSTAT_OK) {
  ------------------
  |  Branch (447:13): [True: 18, False: 6.08k]
  ------------------
  448|     18|            goto cleanup;
  449|     18|        }
  450|  6.09k|    } else {
  451|    558|        if ((retval = read_missing_string_value(ctx, varinfo, 0)) != READSTAT_OK) {
  ------------------
  |  Branch (451:13): [True: 15, False: 543]
  ------------------
  452|     15|            goto cleanup;
  453|     15|        }
  454|    543|        if ((retval = read_missing_string_value(ctx, varinfo, 1)) != READSTAT_OK) {
  ------------------
  |  Branch (454:13): [True: 20, False: 523]
  ------------------
  455|     20|            goto cleanup;
  456|     20|        }
  457|    543|    }
  458|  6.67k|cleanup:
  459|  6.67k|    return retval;
  460|  6.67k|}
readstat_por_read.c:read_missing_value_lo_range_record:
  462|  1.81k|static readstat_error_t read_missing_value_lo_range_record(por_ctx_t *ctx) {
  463|  1.81k|    readstat_error_t retval = READSTAT_OK;
  464|  1.81k|    spss_varinfo_t *varinfo = NULL;
  465|       |
  466|  1.81k|    if (ctx->var_offset < 0 || ctx->var_offset == ctx->var_count) {
  ------------------
  |  Branch (466:9): [True: 1, False: 1.81k]
  |  Branch (466:32): [True: 0, False: 1.81k]
  ------------------
  467|      1|        retval = READSTAT_ERROR_PARSE;
  468|      1|        goto cleanup;
  469|      1|    }
  470|  1.81k|    varinfo = &ctx->varinfo[ctx->var_offset];
  471|       |
  472|  1.81k|    varinfo->missing_range = 1;
  473|  1.81k|    varinfo->n_missing_values = 2;
  474|  1.81k|    if (varinfo->type == READSTAT_TYPE_DOUBLE) {
  ------------------
  |  Branch (474:9): [True: 1.49k, False: 316]
  ------------------
  475|  1.49k|        varinfo->missing_double_values[0] = -HUGE_VAL;
  476|  1.49k|        if ((retval = read_double(ctx, &varinfo->missing_double_values[1])) != READSTAT_OK) {
  ------------------
  |  Branch (476:13): [True: 14, False: 1.48k]
  ------------------
  477|     14|            goto cleanup;
  478|     14|        }
  479|  1.49k|    } else {
  480|    316|        varinfo->missing_string_values[0][0] = '\0';
  481|    316|        if ((retval = read_missing_string_value(ctx, varinfo, 1)) != READSTAT_OK) {
  ------------------
  |  Branch (481:13): [True: 19, False: 297]
  ------------------
  482|     19|            goto cleanup;
  483|     19|        }
  484|    316|    }
  485|  1.81k|cleanup:
  486|  1.81k|    return retval;
  487|  1.81k|}
readstat_por_read.c:read_missing_value_hi_range_record:
  489|  2.57k|static readstat_error_t read_missing_value_hi_range_record(por_ctx_t *ctx) {
  490|  2.57k|    readstat_error_t retval = READSTAT_OK;
  491|  2.57k|    spss_varinfo_t *varinfo = NULL;
  492|       |
  493|  2.57k|    if (ctx->var_offset < 0 || ctx->var_offset == ctx->var_count) {
  ------------------
  |  Branch (493:9): [True: 1, False: 2.57k]
  |  Branch (493:32): [True: 0, False: 2.57k]
  ------------------
  494|      1|        retval = READSTAT_ERROR_PARSE;
  495|      1|        goto cleanup;
  496|      1|    }
  497|  2.57k|    varinfo = &ctx->varinfo[ctx->var_offset];
  498|       |
  499|  2.57k|    varinfo->missing_range = 1;
  500|  2.57k|    varinfo->n_missing_values = 2;
  501|  2.57k|    if (varinfo->type == READSTAT_TYPE_DOUBLE) {
  ------------------
  |  Branch (501:9): [True: 1.61k, False: 957]
  ------------------
  502|  1.61k|        if ((retval = read_double(ctx, &varinfo->missing_double_values[0])) != READSTAT_OK) {
  ------------------
  |  Branch (502:13): [True: 15, False: 1.59k]
  ------------------
  503|     15|            goto cleanup;
  504|     15|        }
  505|  1.59k|        varinfo->missing_double_values[1] = HUGE_VAL;
  506|  1.59k|    } else {
  507|    957|        if ((retval = read_missing_string_value(ctx, varinfo, 0)) != READSTAT_OK) {
  ------------------
  |  Branch (507:13): [True: 9, False: 948]
  ------------------
  508|      9|            goto cleanup;
  509|      9|        }
  510|    948|        varinfo->missing_string_values[1][0] = '\0';
  511|    948|    }
  512|  2.57k|cleanup:
  513|  2.57k|    return retval;
  514|  2.57k|}
readstat_por_read.c:read_variable_label_record:
  539|  1.17k|static readstat_error_t read_variable_label_record(por_ctx_t *ctx) {
  540|  1.17k|    readstat_error_t retval = READSTAT_OK;
  541|  1.17k|    char string[POR_STRING_BUFFER_SIZE];
  542|  1.17k|    spss_varinfo_t *varinfo = NULL;
  543|       |
  544|  1.17k|    if (ctx->var_offset < 0 || ctx->var_offset == ctx->var_count) {
  ------------------
  |  Branch (544:9): [True: 2, False: 1.17k]
  |  Branch (544:32): [True: 0, False: 1.17k]
  ------------------
  545|      2|        retval = READSTAT_ERROR_PARSE;
  546|      2|        goto cleanup;
  547|      2|    }
  548|  1.17k|    varinfo = &ctx->varinfo[ctx->var_offset];
  549|       |
  550|  1.17k|    if ((retval = read_string(ctx, string, sizeof(string))) != READSTAT_OK) {
  ------------------
  |  Branch (550:9): [True: 32, False: 1.14k]
  ------------------
  551|     32|        goto cleanup;
  552|     32|    }
  553|       |
  554|  1.14k|    size_t label_alloc_len = 4*strlen(string) + 1;
  555|  1.14k|    char *new_label = realloc(varinfo->label, label_alloc_len);
  556|  1.14k|    if (new_label == NULL) { retval = READSTAT_ERROR_MALLOC; goto cleanup; }
  ------------------
  |  Branch (556:9): [True: 0, False: 1.14k]
  ------------------
  557|  1.14k|    varinfo->label = new_label;
  558|  1.14k|    retval = readstat_convert(varinfo->label, label_alloc_len, string, strlen(string), ctx->converter);
  559|       |
  560|  1.17k|cleanup:
  561|  1.17k|    return retval;
  562|  1.14k|}
readstat_por_read.c:read_value_label_record:
  564|  5.49k|static readstat_error_t read_value_label_record(por_ctx_t *ctx) {
  565|  5.49k|    readstat_error_t retval = READSTAT_OK;
  566|  5.49k|    double dval;
  567|  5.49k|    int i;
  568|  5.49k|    char string[POR_STRING_BUFFER_SIZE];
  569|  5.49k|    int count = 0, label_count = 0;
  570|  5.49k|    char label_name_buf[256];
  571|  5.49k|    char key_buf[4*POR_STRING_BUFFER_SIZE+1];
  572|  5.49k|    char label_buf[4*POR_STRING_BUFFER_SIZE+1];
  573|  5.49k|    snprintf(label_name_buf, sizeof(label_name_buf), POR_LABEL_NAME_PREFIX "%d", ctx->labels_offset);
  ------------------
  |  |   25|  5.49k|#define POR_LABEL_NAME_PREFIX   "labels"
  ------------------
  574|  5.49k|    readstat_type_t value_type = READSTAT_TYPE_DOUBLE;
  575|  5.49k|    if ((retval = read_integer_in_range(ctx, 0, MAX_STRINGS, &count)) != READSTAT_OK) {
  ------------------
  |  |   38|  5.49k|#define MAX_STRINGS 1000000
  ------------------
  |  Branch (575:9): [True: 21, False: 5.47k]
  ------------------
  576|     21|        goto cleanup;
  577|     21|    }
  578|  10.4k|    for (i=0; i<count; i++) {
  ------------------
  |  Branch (578:15): [True: 5.19k, False: 5.28k]
  ------------------
  579|  5.19k|        if ((retval = read_string(ctx, string, sizeof(string))) != READSTAT_OK) {
  ------------------
  |  Branch (579:13): [True: 187, False: 5.00k]
  ------------------
  580|    187|            goto cleanup;
  581|    187|        }
  582|  5.00k|        spss_varinfo_t *info = (spss_varinfo_t *)ck_str_hash_lookup(string, ctx->var_dict);
  583|  5.00k|        if (info) {
  ------------------
  |  Branch (583:13): [True: 2.15k, False: 2.85k]
  ------------------
  584|  2.15k|            value_type = info->type;
  585|  2.15k|            info->labels_index = ctx->labels_offset;
  586|  2.15k|        }
  587|  5.00k|    }
  588|  5.28k|    if ((retval = read_integer_in_range(ctx, 0, MAX_LABELS, &label_count)) != READSTAT_OK) {
  ------------------
  |  |   39|  5.28k|#define MAX_LABELS  1000000
  ------------------
  |  Branch (588:9): [True: 46, False: 5.23k]
  ------------------
  589|     46|        goto cleanup;
  590|     46|    }
  591|  17.3k|    for (i=0; i<label_count; i++) {
  ------------------
  |  Branch (591:15): [True: 12.1k, False: 5.12k]
  ------------------
  592|  12.1k|        readstat_value_t value = { .type = value_type };
  593|  12.1k|        if (value_type == READSTAT_TYPE_STRING) {
  ------------------
  |  Branch (593:13): [True: 247, False: 11.9k]
  ------------------
  594|    247|            if ((retval = read_converted_string(ctx, key_buf, sizeof(key_buf))) != READSTAT_OK) {
  ------------------
  |  Branch (594:17): [True: 10, False: 237]
  ------------------
  595|     10|                goto cleanup;
  596|     10|            }
  597|    237|            if ((retval = read_converted_string(ctx, label_buf, sizeof(label_buf))) != READSTAT_OK) {
  ------------------
  |  Branch (597:17): [True: 1, False: 236]
  ------------------
  598|      1|                goto cleanup;
  599|      1|            }
  600|    236|            value.v.string_value = key_buf;
  601|  11.9k|        } else {
  602|  11.9k|            if ((retval = read_double(ctx, &dval)) != READSTAT_OK) {
  ------------------
  |  Branch (602:17): [True: 48, False: 11.8k]
  ------------------
  603|     48|                goto cleanup;
  604|     48|            }
  605|  11.8k|            if ((retval = read_converted_string(ctx, label_buf, sizeof(label_buf))) != READSTAT_OK) {
  ------------------
  |  Branch (605:17): [True: 57, False: 11.8k]
  ------------------
  606|     57|                goto cleanup;
  607|     57|            }
  608|  11.8k|            value.v.double_value = dval;
  609|  11.8k|        }
  610|  12.0k|        if (ctx->handle.value_label) {
  ------------------
  |  Branch (610:13): [True: 12.0k, False: 0]
  ------------------
  611|  12.0k|            if (ctx->handle.value_label(label_name_buf, value, label_buf, ctx->user_ctx) != READSTAT_HANDLER_OK) {
  ------------------
  |  |   22|  12.0k|#define READSTAT_HANDLER_OK             0
  ------------------
  |  Branch (611:17): [True: 0, False: 12.0k]
  ------------------
  612|      0|                retval = READSTAT_ERROR_USER_ABORT;
  613|      0|                goto cleanup;
  614|      0|            }
  615|  12.0k|        }
  616|  12.0k|    }
  617|  5.12k|    ctx->labels_offset++;
  618|       |
  619|  5.49k|cleanup:
  620|  5.49k|    return retval;
  621|  5.12k|}
readstat_por_read.c:read_document_record:
  516|    750|static readstat_error_t read_document_record(por_ctx_t *ctx) {
  517|    750|    readstat_error_t retval = READSTAT_OK;
  518|    750|    char string[4*POR_STRING_BUFFER_SIZE+1];
  519|    750|    int i;
  520|    750|    int line_count = 0;
  521|    750|    if ((retval = read_integer_in_range(ctx, 0, MAX_LINES, &line_count)) != READSTAT_OK) {
  ------------------
  |  |   37|    750|#define MAX_LINES   1000000
  ------------------
  |  Branch (521:9): [True: 14, False: 736]
  ------------------
  522|     14|        goto cleanup;
  523|     14|    }
  524|  2.24k|    for (i=0; i<line_count; i++) {
  ------------------
  |  Branch (524:15): [True: 1.57k, False: 670]
  ------------------
  525|  1.57k|        if ((retval = read_converted_string(ctx, string, sizeof(string))) != READSTAT_OK) {
  ------------------
  |  Branch (525:13): [True: 66, False: 1.51k]
  ------------------
  526|     66|            goto cleanup;
  527|     66|        }
  528|  1.51k|        if (ctx->handle.note) {
  ------------------
  |  Branch (528:13): [True: 1.51k, False: 0]
  ------------------
  529|  1.51k|            if (ctx->handle.note(i, string, ctx->user_ctx) != READSTAT_OK) {
  ------------------
  |  Branch (529:17): [True: 0, False: 1.51k]
  ------------------
  530|      0|                retval = READSTAT_ERROR_USER_ABORT;
  531|      0|                goto cleanup;
  532|      0|            }
  533|  1.51k|        }
  534|  1.51k|    }
  535|    750|cleanup:
  536|    750|    return retval;
  537|    736|}
readstat_por_read.c:read_por_file_data:
  623|    380|static readstat_error_t read_por_file_data(por_ctx_t *ctx) {
  624|    380|    int i;
  625|    380|    char input_string[POR_STRING_BUFFER_SIZE];
  626|    380|    char output_string[4*POR_STRING_BUFFER_SIZE+1];
  627|    380|    char error_buf[1024];
  628|    380|    readstat_error_t rs_retval = READSTAT_OK;
  629|       |
  630|    380|    if (ctx->var_count == 0)
  ------------------
  |  Branch (630:9): [True: 8, False: 372]
  ------------------
  631|      8|        return READSTAT_OK;
  632|       |
  633|  11.1k|    while (1) {
  ------------------
  |  Branch (633:12): [True: 11.1k, Folded]
  ------------------
  634|  11.1k|        int finished = 0;
  635|  25.5k|        for (i=0; i<ctx->var_count; i++) {
  ------------------
  |  Branch (635:19): [True: 14.7k, False: 10.8k]
  ------------------
  636|  14.7k|            spss_varinfo_t *info = &ctx->varinfo[i];
  637|  14.7k|            readstat_value_t value = { .type = info->type };
  638|       |
  639|  14.7k|            if (info->type == READSTAT_TYPE_STRING) {
  ------------------
  |  Branch (639:17): [True: 429, False: 14.3k]
  ------------------
  640|    429|                rs_retval = maybe_read_string(ctx, input_string, sizeof(input_string), &finished);
  641|    429|                if (rs_retval != READSTAT_OK) {
  ------------------
  |  Branch (641:21): [True: 166, False: 263]
  ------------------
  642|    166|                    if (ctx->handle.error) {
  ------------------
  |  Branch (642:25): [True: 0, False: 166]
  ------------------
  643|      0|                        snprintf(error_buf, sizeof(error_buf), "Error in %s (row=%d)", 
  644|      0|                                info->name, ctx->obs_count+1);
  645|      0|                        ctx->handle.error(error_buf, ctx->user_ctx);
  646|      0|                    }
  647|    166|                    goto cleanup;
  648|    263|                } else if (finished) {
  ------------------
  |  Branch (648:28): [True: 3, False: 260]
  ------------------
  649|      3|                    if (i != 0)
  ------------------
  |  Branch (649:25): [True: 2, False: 1]
  ------------------
  650|      2|                        rs_retval = READSTAT_ERROR_PARSE;
  651|      3|                    goto cleanup;
  652|      3|                }
  653|    260|                rs_retval = readstat_convert(output_string, sizeof(output_string),
  654|    260|                        input_string, strlen(input_string), ctx->converter);
  655|    260|                if (rs_retval != READSTAT_OK) {
  ------------------
  |  Branch (655:21): [True: 0, False: 260]
  ------------------
  656|      0|                    goto cleanup;
  657|      0|                }
  658|    260|                value.v.string_value = output_string;
  659|  14.3k|            } else if (info->type == READSTAT_TYPE_DOUBLE) {
  ------------------
  |  Branch (659:24): [True: 14.3k, False: 0]
  ------------------
  660|  14.3k|                rs_retval = maybe_read_double(ctx, &value.v.double_value, &finished);
  661|  14.3k|                if (rs_retval != READSTAT_OK) {
  ------------------
  |  Branch (661:21): [True: 200, False: 14.1k]
  ------------------
  662|    200|                    if (ctx->handle.error) {
  ------------------
  |  Branch (662:25): [True: 0, False: 200]
  ------------------
  663|      0|                        snprintf(error_buf, sizeof(error_buf), "Error in %s (row=%d)", 
  664|      0|                                info->name, ctx->obs_count+1);
  665|      0|                        ctx->handle.error(error_buf, ctx->user_ctx);
  666|      0|                    }
  667|    200|                    goto cleanup;
  668|  14.1k|                } else if (finished) {
  ------------------
  |  Branch (668:28): [True: 3, False: 14.1k]
  ------------------
  669|      3|                    if (i != 0)
  ------------------
  |  Branch (669:25): [True: 2, False: 1]
  ------------------
  670|      2|                        rs_retval = READSTAT_ERROR_PARSE;
  671|      3|                    goto cleanup;
  672|      3|                }
  673|  14.1k|                value.is_system_missing = isnan(value.v.double_value);
  674|  14.1k|            }
  675|  14.3k|            if (ctx->handle.value && !ctx->variables[i]->skip && !ctx->row_offset) {
  ------------------
  |  Branch (675:17): [True: 14.3k, False: 0]
  |  Branch (675:38): [True: 14.3k, False: 0]
  |  Branch (675:66): [True: 14.3k, False: 0]
  ------------------
  676|  14.3k|                if (ctx->handle.value(ctx->obs_count, ctx->variables[i], value, ctx->user_ctx) != READSTAT_HANDLER_OK) {
  ------------------
  |  |   22|  14.3k|#define READSTAT_HANDLER_OK             0
  ------------------
  |  Branch (676:21): [True: 0, False: 14.3k]
  ------------------
  677|      0|                    rs_retval = READSTAT_ERROR_USER_ABORT;
  678|      0|                    goto cleanup;
  679|      0|                }
  680|  14.3k|            }
  681|       |
  682|  14.3k|        }
  683|  10.8k|        if (ctx->row_offset) {
  ------------------
  |  Branch (683:13): [True: 0, False: 10.8k]
  ------------------
  684|      0|            ctx->row_offset--;
  685|  10.8k|        } else {
  686|  10.8k|            ctx->obs_count++;
  687|  10.8k|        }
  688|       |
  689|  10.8k|        rs_retval = por_update_progress(ctx);
  690|  10.8k|        if (rs_retval != READSTAT_OK)
  ------------------
  |  Branch (690:13): [True: 0, False: 10.8k]
  ------------------
  691|      0|            break;
  692|       |            
  693|  10.8k|        if (ctx->row_limit > 0 && ctx->obs_count == ctx->row_limit)
  ------------------
  |  Branch (693:13): [True: 0, False: 10.8k]
  |  Branch (693:35): [True: 0, False: 0]
  ------------------
  694|      0|            break;
  695|  10.8k|    }
  696|    372|cleanup:
  697|    372|    return rs_retval;
  698|    372|}
readstat_por_read.c:por_update_progress:
   44|  10.8k|static readstat_error_t por_update_progress(por_ctx_t *ctx) {
   45|  10.8k|    readstat_io_t *io = ctx->io;
   46|  10.8k|    return io->update(ctx->file_size, ctx->handle.progress, ctx->user_ctx, io->io_ctx);
   47|  10.8k|}

spss_format:
   51|  1.66k|int spss_format(char *buffer, size_t len, spss_format_t *format) {
   52|  1.66k|    if (format->type < 0 
  ------------------
  |  Branch (52:9): [True: 0, False: 1.66k]
  ------------------
   53|  1.66k|            || format->type >= sizeof(spss_type_strings)/sizeof(spss_type_strings[0])
  ------------------
  |  Branch (53:16): [True: 12, False: 1.65k]
  ------------------
   54|  1.65k|            || spss_type_strings[format->type][0] == '\0') {
  ------------------
  |  Branch (54:16): [True: 573, False: 1.08k]
  ------------------
   55|    585|        return 0;
   56|    585|    }
   57|  1.08k|    char *string = spss_type_strings[format->type];
   58|       |
   59|  1.08k|    if (format->decimal_places || format->type == SPSS_FORMAT_TYPE_F) {
  ------------------
  |  |    6|    466|#define SPSS_FORMAT_TYPE_F        5
  ------------------
  |  Branch (59:9): [True: 616, False: 466]
  |  Branch (59:35): [True: 184, False: 282]
  ------------------
   60|    800|        snprintf(buffer, len, "%s%d.%d", string, format->width, format->decimal_places);
   61|    800|    } else if (format->width) {
  ------------------
  |  Branch (61:16): [True: 202, False: 80]
  ------------------
   62|    202|        snprintf(buffer, len, "%s%d", string, format->width);
   63|    202|    } else {
   64|     80|        snprintf(buffer, len, "%s", string);
   65|     80|    }
   66|       |
   67|  1.08k|    return 1;
   68|  1.66k|}
spss_missingness_for_info:
  127|  1.66k|readstat_missingness_t spss_missingness_for_info(spss_varinfo_t *info) {
  128|  1.66k|    readstat_missingness_t missingness;
  129|  1.66k|    memset(&missingness, '\0', sizeof(readstat_missingness_t));
  130|       |
  131|  1.66k|    if (info->missing_range) {
  ------------------
  |  Branch (131:9): [True: 126, False: 1.54k]
  ------------------
  132|    126|        missingness.missing_ranges_count++;
  133|    126|        missingness.missing_ranges[0] = spss_boxed_missing_value(info, 0);
  134|    126|        missingness.missing_ranges[1] = spss_boxed_missing_value(info, 1);
  135|       |
  136|    126|        if (info->n_missing_values == 3) {
  ------------------
  |  Branch (136:13): [True: 36, False: 90]
  ------------------
  137|     36|            missingness.missing_ranges_count++;
  138|     36|            missingness.missing_ranges[2] = missingness.missing_ranges[3] = spss_boxed_missing_value(info, 2);
  139|     36|        }
  140|  1.54k|    } else if (info->n_missing_values > 0) {
  ------------------
  |  Branch (140:16): [True: 124, False: 1.41k]
  ------------------
  141|    124|        missingness.missing_ranges_count = info->n_missing_values;
  142|    124|        int i=0;
  143|    310|        for (i=0; i<info->n_missing_values; i++) {
  ------------------
  |  Branch (143:19): [True: 186, False: 124]
  ------------------
  144|    186|            missingness.missing_ranges[2*i] = missingness.missing_ranges[2*i+1] = spss_boxed_missing_value(info, i);
  145|    186|        }
  146|    124|    }
  147|  1.66k|    return missingness;
  148|  1.66k|}
spss_init_variable_for_info:
  151|  1.66k|        iconv_t converter) {
  152|  1.66k|    readstat_variable_t *variable = calloc(1, sizeof(readstat_variable_t));
  153|       |
  154|  1.66k|    variable->index = info->index;
  155|  1.66k|    variable->index_after_skipping = index_after_skipping;
  156|  1.66k|    variable->type = info->type;
  157|  1.66k|    if (info->string_length) {
  ------------------
  |  Branch (157:9): [True: 948, False: 719]
  ------------------
  158|    948|        variable->storage_width = info->string_length;
  159|    948|    } else {
  160|    719|        variable->storage_width = 8 * info->width;
  161|    719|    }
  162|       |
  163|  1.66k|    if (info->longname[0]) {
  ------------------
  |  Branch (163:9): [True: 0, False: 1.66k]
  ------------------
  164|      0|        readstat_convert(variable->name, sizeof(variable->name),
  165|      0|                info->longname, sizeof(info->longname), converter);
  166|  1.66k|    } else {
  167|  1.66k|        readstat_convert(variable->name, sizeof(variable->name),
  168|  1.66k|                info->name, sizeof(info->name), converter);
  169|  1.66k|    }
  170|  1.66k|    if (info->label) {
  ------------------
  |  Branch (170:9): [True: 54, False: 1.61k]
  ------------------
  171|     54|        snprintf(variable->label, sizeof(variable->label), "%s", info->label);
  172|     54|    }
  173|       |
  174|  1.66k|    spss_format(variable->format, sizeof(variable->format), &info->print_format);
  175|       |
  176|  1.66k|    variable->missingness = spss_missingness_for_info(info);
  177|  1.66k|    variable->measure = info->measure;
  178|  1.66k|    variable->alignment = info->alignment;
  179|  1.66k|    if (info->display_width) {
  ------------------
  |  Branch (179:9): [True: 0, False: 1.66k]
  ------------------
  180|      0|        variable->display_width = info->display_width;
  181|  1.66k|    } else {
  182|  1.66k|        variable->display_width = info->print_format.width;
  183|  1.66k|    }
  184|       |
  185|  1.66k|    return variable;
  186|  1.66k|}
readstat_spss.c:spss_boxed_missing_value:
  120|    474|static readstat_value_t spss_boxed_missing_value(spss_varinfo_t *info, int i) {
  121|    474|    if (info->type == READSTAT_TYPE_DOUBLE) {
  ------------------
  |  Branch (121:9): [True: 302, False: 172]
  ------------------
  122|    302|        return spss_boxed_double_value(info->missing_double_values[i]);
  123|    302|    }
  124|    172|    return spss_boxed_string_value(info->missing_string_values[i]);
  125|    474|}
readstat_spss.c:spss_boxed_double_value:
  103|    302|static readstat_value_t spss_boxed_double_value(double fp_value) {
  104|    302|    readstat_value_t value = {
  105|    302|        .type = READSTAT_TYPE_DOUBLE,
  106|    302|        .v = { .double_value = fp_value },
  107|       |        .is_system_missing = isnan(fp_value)
  108|    302|    };
  109|    302|    return value;
  110|    302|}
readstat_spss.c:spss_boxed_string_value:
  112|    172|static readstat_value_t spss_boxed_string_value(const char *string) {
  113|    172|    readstat_value_t value = {
  114|    172|        .type = READSTAT_TYPE_STRING,
  115|    172|        .v = { .string_value = string }
  116|    172|    };
  117|    172|    return value;
  118|    172|}

rt_open_handler:
    8|  2.81k|int rt_open_handler(const char *path, void *io_ctx) {
    9|  2.81k|    return 0;
   10|  2.81k|}
rt_close_handler:
   12|  2.81k|int rt_close_handler(void *io_ctx) {
   13|  2.81k|    return 0;
   14|  2.81k|}
rt_seek_handler:
   17|  5.62k|        readstat_io_flags_t whence, void *io_ctx) {
   18|  5.62k|    rt_buffer_ctx_t *buffer_ctx = (rt_buffer_ctx_t *)io_ctx;
   19|  5.62k|    readstat_off_t newpos = -1;
   20|  5.62k|    if (whence == READSTAT_SEEK_SET) {
  ------------------
  |  Branch (20:9): [True: 2.81k, False: 2.81k]
  ------------------
   21|  2.81k|        newpos = offset;
   22|  2.81k|    } else if (whence == READSTAT_SEEK_CUR) {
  ------------------
  |  Branch (22:16): [True: 0, False: 2.81k]
  ------------------
   23|      0|        newpos = buffer_ctx->pos + offset;
   24|  2.81k|    } else if (whence == READSTAT_SEEK_END) {
  ------------------
  |  Branch (24:16): [True: 2.81k, False: 0]
  ------------------
   25|  2.81k|        newpos = buffer_ctx->buffer->used + offset;
   26|  2.81k|    }
   27|       |
   28|  5.62k|    if (newpos < 0)
  ------------------
  |  Branch (28:9): [True: 0, False: 5.62k]
  ------------------
   29|      0|        return -1;
   30|       |
   31|  5.62k|    if (newpos > buffer_ctx->buffer->used)
  ------------------
  |  Branch (31:9): [True: 0, False: 5.62k]
  ------------------
   32|      0|        return -1;
   33|       |
   34|  5.62k|    buffer_ctx->pos = newpos;
   35|  5.62k|    return newpos;
   36|  5.62k|}
rt_read_handler:
   38|  1.75M|ssize_t rt_read_handler(void *buf, size_t nbytes, void *io_ctx) {
   39|  1.75M|    rt_buffer_ctx_t *buffer_ctx = (rt_buffer_ctx_t *)io_ctx;
   40|  1.75M|    ssize_t bytes_copied = 0;
   41|  1.75M|    ssize_t bytes_left = buffer_ctx->buffer->used - buffer_ctx->pos;
   42|  1.75M|    if (nbytes <= bytes_left) {
  ------------------
  |  Branch (42:9): [True: 1.75M, False: 1.87k]
  ------------------
   43|  1.75M|        memcpy(buf, buffer_ctx->buffer->bytes + buffer_ctx->pos, nbytes);
   44|  1.75M|        bytes_copied = nbytes;
   45|  1.75M|    } else if (bytes_left > 0) {
  ------------------
  |  Branch (45:16): [True: 0, False: 1.87k]
  ------------------
   46|      0|        memcpy(buf, buffer_ctx->buffer->bytes + buffer_ctx->pos, bytes_left);
   47|      0|        bytes_copied = bytes_left;
   48|      0|    }
   49|  1.75M|    buffer_ctx->pos += bytes_copied;
   50|  1.75M|    return bytes_copied;
   51|  1.75M|}
rt_update_handler:
   54|  10.8k|        void *user_ctx, void *io_ctx) {
   55|  10.8k|    if (!progress_handler)
  ------------------
  |  Branch (55:9): [True: 10.8k, False: 0]
  ------------------
   56|  10.8k|        return READSTAT_OK;
   57|       |
   58|      0|    rt_buffer_ctx_t *buffer_ctx = (rt_buffer_ctx_t *)io_ctx;
   59|       |
   60|      0|    if (progress_handler(1.0 * buffer_ctx->pos / buffer_ctx->buffer->used, user_ctx))
  ------------------
  |  Branch (60:9): [True: 0, False: 0]
  ------------------
   61|      0|        return READSTAT_ERROR_USER_ABORT;
   62|       |
   63|      0|    return READSTAT_OK;
   64|      0|}

