1 /*
2  * Copyright (c) 2003-2014 Tony Bybell.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  * DEALINGS IN THE SOFTWARE.
21  */
22 
23 #include <config.h>
24 #include "lxt2_read.h"
25 
26 /****************************************************************************/
27 
28 #ifdef _WAVE_BE32
29 
30 /*
31  * reconstruct 8/16/24/32 bits out of the lxt's representation
32  * of a big-endian integer.  this is for 32-bit PPC so no byte
33  * swizzling needs to be done at all.  for 24-bit ints, we have no danger of
34  * running off the end of memory provided we do the "-1" trick
35  * since we'll never read a 24-bit int at the very start of a file which
36  * means that we'll have a 32-bit word that we can read.
37  */
38 
39 #define lxt2_rd_get_byte(mm,offset)    ((unsigned int)(*((unsigned char *)(mm)+(offset))))
40 #define lxt2_rd_get_16(mm,offset)      ((unsigned int)(*((unsigned short *)(((unsigned char *)(mm))+(offset)))))
41 #define lxt2_rd_get_32(mm,offset)      (*(unsigned int *)(((unsigned char *)(mm))+(offset)))
42 #define lxt2_rd_get_24(mm,offset)      ((lxt2_rd_get_32((mm),(offset)-1)<<8)>>8)
43 #define lxt2_rd_get_64(mm,offset)      ((((lxtint64_t)lxt2_rd_get_32((mm),(offset)))<<32)|((lxtint64_t)lxt2_rd_get_32((mm),(offset)+4)))
44 
45 #else
46 
47 /*
48  * reconstruct 8/16/24/32 bits out of the lxt's representation
49  * of a big-endian integer.  this should work on all architectures.
50  */
51 #define lxt2_rd_get_byte(mm,offset) 	((unsigned int)(*((unsigned char *)(mm)+(offset))))
52 
lxt2_rd_get_16(void * mm,int offset)53 static unsigned int lxt2_rd_get_16(void *mm, int offset)
54 {
55 unsigned char *nn=(unsigned char *)mm+offset;
56 unsigned int m1=*((unsigned char *)(nn++));
57 unsigned int m2=*((unsigned char *)nn);
58 return((m1<<8)|m2);
59 }
60 
lxt2_rd_get_24(void * mm,int offset)61 static unsigned int lxt2_rd_get_24(void *mm,int offset)
62 {
63 unsigned char *nn=(unsigned char *)mm+offset;
64 unsigned int m1=*((unsigned char *)(nn++));
65 unsigned int m2=*((unsigned char *)(nn++));
66 unsigned int m3=*((unsigned char *)nn);
67 return((m1<<16)|(m2<<8)|m3);
68 }
69 
lxt2_rd_get_32(void * mm,int offset)70 static unsigned int lxt2_rd_get_32(void *mm, int offset)
71 {
72 unsigned char *nn=(unsigned char *)mm+offset;
73 unsigned int m1=*((unsigned char *)(nn++));
74 unsigned int m2=*((unsigned char *)(nn++));
75 unsigned int m3=*((unsigned char *)(nn++));
76 unsigned int m4=*((unsigned char *)nn);
77 return((m1<<24)|(m2<<16)|(m3<<8)|m4);
78 }
79 
lxt2_rd_get_64(void * mm,int offset)80 static lxtint64_t lxt2_rd_get_64(void *mm, int offset)
81 {
82 return(
83 (((lxtint64_t)lxt2_rd_get_32(mm,offset))<<32)
84 |((lxtint64_t)lxt2_rd_get_32(mm,offset+4))
85 );
86 }
87 
88 #endif
89 
90 /****************************************************************************/
91 
92 /*
93  * fast SWAR ones count for 32 and 64 bits
94  */
95 #if LXT2_RD_GRANULE_SIZE > 32
96 
97 _LXT2_RD_INLINE granmsk_t
lxt2_rd_ones_cnt(granmsk_t x)98 lxt2_rd_ones_cnt(granmsk_t x)
99 {
100 x -= ((x >> 1) & LXT2_RD_ULLDESC(0x5555555555555555));
101 x = (((x >> 2) & LXT2_RD_ULLDESC(0x3333333333333333)) + (x & LXT2_RD_ULLDESC(0x3333333333333333)));
102 x = (((x >> 4) + x) & LXT2_RD_ULLDESC(0x0f0f0f0f0f0f0f0f));
103 return((x * LXT2_RD_ULLDESC(0x0101010101010101)) >> 56);
104 }
105 
106 #else
107 
108 _LXT2_RD_INLINE granmsk_t
lxt2_rd_ones_cnt(granmsk_t x)109 lxt2_rd_ones_cnt(granmsk_t x)
110 {
111 x -= ((x >> 1) & 0x55555555);
112 x = (((x >> 2) & 0x33333333) + (x & 0x33333333));
113 x = (((x >> 4) + x) & 0x0f0f0f0f);
114 return((x * 0x01010101) >> 24);
115 }
116 
117 #endif
118 
119 
120 /*
121  * total zero count to the right of the first rightmost one bit
122  * encountered.  its intended use is to
123  * "return the bitposition of the least significant 1 in a granmsk_t"
124  * (use x &= ~(x&-x) to clear out that bit quickly)
125  */
126 _LXT2_RD_INLINE granmsk_t
lxt2_rd_tzc(granmsk_t x)127 lxt2_rd_tzc(granmsk_t x)
128 {
129 return (lxt2_rd_ones_cnt((x & -x) - LXT2_RD_GRAN_1VAL));
130 }
131 
132 /****************************************************************************/
133 
134 /*
135  * i2c and c2i utility functions
136  */
lxt2_rd_expand_integer_to_bits(int len,unsigned int value)137 static char *lxt2_rd_expand_integer_to_bits(int len, unsigned int value)
138 {
139 static char s[33];
140 char *p = s;
141 int i;
142 int len2 = len-1;
143 
144 for(i=0;i<len;i++)
145         {
146         *(p++) = '0' | ((value & (1<<(len2-i)))!=0);
147         }
148 *p = 0;
149 
150 return(s);
151 }
152 
153 
lxt2_rd_expand_bits_to_integer(int len,char * s)154 unsigned int lxt2_rd_expand_bits_to_integer(int len, char *s)
155 {
156 unsigned int v = 0;
157 int i;
158 
159 for(i=0;i<len;i++)
160 	{
161 	v <<= 1;
162 	v |= ((*s) & 1);
163 	s++;
164 	}
165 
166 return(v);
167 }
168 
169 
170 /*
171  * called for all value changes except for the 1st one in a block
172  * (as they're all unique based on the timeslot scheme, no duplicate
173  * checking is necessary...)
174  */
lxt2_rd_iter_radix(struct lxt2_rd_trace * lt,struct lxt2_rd_block * b)175 void lxt2_rd_iter_radix(struct lxt2_rd_trace *lt, struct lxt2_rd_block *b)
176 {
177 unsigned int which_time;
178 int offset;
179 void **top_elem;
180 granmsk_t msk = ~LXT2_RD_GRAN_1VAL;
181 lxtint32_t x;
182 
183 for(which_time = 0; which_time < lt->num_time_table_entries; which_time++, msk <<= 1)
184 while((top_elem = lt->radix_sort[which_time]))
185 	{
186 	lxtint32_t idx = top_elem - lt->next_radix;
187 	unsigned int vch;
188 	lxtint32_t i;
189 
190 	switch(lt->fac_curpos_width)
191 		{
192 		case 1:	vch = lxt2_rd_get_byte(lt->fac_curpos[idx], 0); break;
193 		case 2:	vch = lxt2_rd_get_16(lt->fac_curpos[idx], 0); break;
194 		case 3:	vch = lxt2_rd_get_24(lt->fac_curpos[idx], 0); break;
195 		case 4:
196 		default:
197 			vch = lxt2_rd_get_32(lt->fac_curpos[idx], 0); break;
198 		}
199 
200 	lt->fac_curpos[idx] += lt->fac_curpos_width;
201 
202 	offset = lxt2_rd_tzc(lt->fac_map[idx] &= msk);		/* offset = next "which time" for this fac */
203 
204 	lt->radix_sort[which_time] = lt->next_radix[idx];	/* get next list item for this "which time" bucket */
205 
206 	lt->next_radix[idx] = lt->radix_sort[offset]; 		/* promote fac to its next (higher) possible bucket (if any) */
207         lt->radix_sort[offset] = &lt->next_radix[idx];		/* ...and put it at the head of that list */
208 
209 	switch(vch)
210 		{
211         	case LXT2_RD_ENC_0:
212         	case LXT2_RD_ENC_1:	memset(lt->value[idx], '0'+(vch-LXT2_RD_ENC_0), lt->len[idx]); break;
213 
214         	case LXT2_RD_ENC_INV:	for(i=0;i<lt->len[idx];i++) { lt->value[idx][i] ^= 1; } break;
215 
216         	case LXT2_RD_ENC_LSH0:
217         	case LXT2_RD_ENC_LSH1:	memmove(lt->value[idx], lt->value[idx]+1, lt->len[idx]-1);
218 					lt->value[idx][lt->len[idx]-1] = '0'+(vch-LXT2_RD_ENC_LSH0);
219 					break;
220 
221         	case LXT2_RD_ENC_RSH0:
222         	case LXT2_RD_ENC_RSH1:	memmove(lt->value[idx]+1, lt->value[idx], lt->len[idx]-1);
223 					lt->value[idx][0] = '0'+(vch-LXT2_RD_ENC_RSH0);
224 					break;
225 
226 		case LXT2_RD_ENC_ADD1:
227 		case LXT2_RD_ENC_ADD2:
228 		case LXT2_RD_ENC_ADD3:
229         	case LXT2_RD_ENC_ADD4:	x=lxt2_rd_expand_bits_to_integer(lt->len[idx], lt->value[idx]); x+= (vch-LXT2_RD_ENC_ADD1+1);
230 					memcpy(lt->value[idx], lxt2_rd_expand_integer_to_bits(lt->len[idx], x), lt->len[idx]); break;
231 
232 		case LXT2_RD_ENC_SUB1:
233 		case LXT2_RD_ENC_SUB2:
234 		case LXT2_RD_ENC_SUB3:
235         	case LXT2_RD_ENC_SUB4:	x=lxt2_rd_expand_bits_to_integer(lt->len[idx], lt->value[idx]); x-= (vch-LXT2_RD_ENC_SUB1+1);
236 					memcpy(lt->value[idx], lxt2_rd_expand_integer_to_bits(lt->len[idx], x), lt->len[idx]); break;
237 
238         	case LXT2_RD_ENC_X:	memset(lt->value[idx], 'x', lt->len[idx]); break;
239         	case LXT2_RD_ENC_Z:	memset(lt->value[idx], 'z', lt->len[idx]); break;
240 
241 		case LXT2_RD_ENC_BLACKOUT:
242 					lt->value[idx][0] = 0; break;
243 
244 		default:		vch -= LXT2_RD_DICT_START;
245 					if(vch >= b->num_dict_entries)
246 						{
247 						fprintf(stderr, LXT2_RDLOAD"Internal error: vch(%d) >= num_dict_entries("LXT2_RD_LD")\n", vch, b->num_dict_entries);
248 						exit(255);
249 						}
250 
251 					if(lt->flags[idx] & (LXT2_RD_SYM_F_DOUBLE|LXT2_RD_SYM_F_STRING))
252 						{
253 						/* fprintf(stderr, LXT2_RDLOAD"DOUBLE: %s\n", b->string_pointers[vch]); */
254 						free(lt->value[idx]);
255 						lt->value[idx] = strdup(b->string_pointers[vch]);
256 						break;
257 						}
258 
259 					if(lt->len[idx] == b->string_lens[vch])
260 						{
261 						memcpy(lt->value[idx],  b->string_pointers[vch], lt->len[idx]);
262 						}
263 					else
264 					if(lt->len[idx] > b->string_lens[vch])
265 						{
266 						int lendelta = lt->len[idx] - b->string_lens[vch];
267 				                memset(lt->value[idx], (b->string_pointers[vch][0]!='1') ?  b->string_pointers[vch][0] : '0', lendelta);
268                 				strcpy(lt->value[idx]+lendelta,  b->string_pointers[vch]);
269 						}
270 					else
271 						{
272 						fprintf(stderr, LXT2_RDLOAD"Internal error "LXT2_RD_LD" ('%s') vs %d ('%s')\n",
273 							lt->len[idx], lt->value[idx],
274 							b->string_lens[vch], b->string_pointers[vch]);
275 						exit(255);
276 						}
277 
278 					break;
279 		}
280 
281 	/* this string is _always_ unique */
282 	/* fprintf(stderr, LXT2_RDLOAD"%lld : [%d] '%s'\n", lt->time_table[which_time], idx, lt->value[idx]); */
283 
284 	if(lt->time_table[which_time] != lt->prev_time)
285 		{
286 		lt->prev_time = lt->time_table[which_time];
287 		}
288 
289 	lt->value_change_callback(&lt, &lt->time_table[which_time], &idx, &lt->value[idx]);
290 	}
291 }
292 
293 
294 /*
295  * called for only 1st vch in a block: blocks out emission of duplicate
296  * vch from preceeding block
297  */
lxt2_rd_iter_radix0(struct lxt2_rd_trace * lt,struct lxt2_rd_block * b,lxtint32_t idx)298 void lxt2_rd_iter_radix0(struct lxt2_rd_trace *lt, struct lxt2_rd_block *b, lxtint32_t idx)
299 {
300 	unsigned int vch;
301 	unsigned int which_time;
302 	lxtint32_t i;
303 	int uniq = 0;
304 
305 	switch(lt->fac_curpos_width)
306 		{
307 		case 1:	vch = lxt2_rd_get_byte(lt->fac_curpos[idx], 0); break;
308 		case 2:	vch = lxt2_rd_get_16(lt->fac_curpos[idx], 0); break;
309 		case 3:	vch = lxt2_rd_get_24(lt->fac_curpos[idx], 0); break;
310 		case 4:
311 		default:
312 			vch = lxt2_rd_get_32(lt->fac_curpos[idx], 0); break;
313 		}
314 
315 	lt->fac_curpos[idx] += lt->fac_curpos_width;
316 	which_time = 0;
317 
318 	switch(vch)
319 		{
320         	case LXT2_RD_ENC_0:		for(i=0;i<lt->len[idx];i++)
321 						{
322 						if(lt->value[idx][i]!='0')
323 							{
324 							memset(lt->value[idx]+i, '0', lt->len[idx] - i);
325 							uniq = 1;
326 							break;
327 							}
328 						}
329 					break;
330 
331         	case LXT2_RD_ENC_1:		for(i=0;i<lt->len[idx];i++)
332 						{
333 						if(lt->value[idx][i]!='1')
334 							{
335 							memset(lt->value[idx]+i, '1', lt->len[idx] - i);
336 							uniq = 1;
337 							break;
338 							}
339 						}
340 					break;
341 
342         	case LXT2_RD_ENC_INV:
343         	case LXT2_RD_ENC_LSH0:
344         	case LXT2_RD_ENC_LSH1:
345         	case LXT2_RD_ENC_RSH0:
346         	case LXT2_RD_ENC_RSH1:
347 		case LXT2_RD_ENC_ADD1:
348 		case LXT2_RD_ENC_ADD2:
349 		case LXT2_RD_ENC_ADD3:
350         	case LXT2_RD_ENC_ADD4:
351 		case LXT2_RD_ENC_SUB1:
352 		case LXT2_RD_ENC_SUB2:
353 		case LXT2_RD_ENC_SUB3:
354         	case LXT2_RD_ENC_SUB4:	fprintf(stderr, LXT2_RDLOAD"Internal error in granule 0 position 0\n");
355 					exit(255);
356 
357         	case LXT2_RD_ENC_X:	for(i=0;i<lt->len[idx];i++)
358 						{
359 						if(lt->value[idx][i]!='x')
360 							{
361 							memset(lt->value[idx]+i, 'x', lt->len[idx] - i);
362 							uniq = 1;
363 							break;
364 							}
365 						}
366 					break;
367 
368         	case LXT2_RD_ENC_Z:	for(i=0;i<lt->len[idx];i++)
369 						{
370 						if(lt->value[idx][i]!='z')
371 							{
372 							memset(lt->value[idx]+i, 'z', lt->len[idx] - i);
373 							uniq = 1;
374 							break;
375 							}
376 						}
377 					break;
378 
379 		case LXT2_RD_ENC_BLACKOUT:
380 					if(lt->value[idx])
381 						{
382 						lt->value[idx][0] = 0;
383 						uniq=1;
384 						}
385 					break;
386 
387 		default:		vch -= LXT2_RD_DICT_START;
388 					if(vch >= b->num_dict_entries)
389 						{
390 						fprintf(stderr, LXT2_RDLOAD"Internal error: vch(%d) >= num_dict_entries("LXT2_RD_LD")\n", vch, b->num_dict_entries);
391 						exit(255);
392 						}
393 
394 					if(lt->flags[idx] & (LXT2_RD_SYM_F_DOUBLE|LXT2_RD_SYM_F_STRING))
395 						{
396 						/* fprintf(stderr, LXT2_RDLOAD"DOUBLE: %s\n", b->string_pointers[vch]); */
397 						if(strcmp(lt->value[idx], b->string_pointers[vch]))
398 							{
399 							free(lt->value[idx]);
400 							lt->value[idx] = strdup(b->string_pointers[vch]);
401 							uniq = 1;
402 							}
403 						break;
404 						}
405 
406 					if(lt->len[idx] == b->string_lens[vch])
407 						{
408 						for(i=0;i<lt->len[idx];i++)
409 							{
410 							if(lt->value[idx][i] != b->string_pointers[vch][i])
411 								{
412 								memcpy(lt->value[idx]+i,  b->string_pointers[vch]+i, lt->len[idx]-i);
413 								uniq = 1;
414 								}
415 							}
416 						}
417 					else
418 					if(lt->len[idx] > b->string_lens[vch])
419 						{
420 						lxtint32_t lendelta = lt->len[idx] - b->string_lens[vch];
421 						int fill = (b->string_pointers[vch][0]!='1') ?  b->string_pointers[vch][0] : '0';
422 
423 						for(i=0;i<lendelta;i++)
424 							{
425 							if (lt->value[idx][i] != fill)
426 								{
427 								memset(lt->value[idx] + i, fill, lendelta - i);
428 		                				strcpy(lt->value[idx]+lendelta,  b->string_pointers[vch]);
429 								uniq = 1;
430 								goto fini;
431 								}
432 							}
433 
434 						for(i=lendelta;i<lt->len[idx];i++)
435 							{
436 							if(lt->value[idx][i] != b->string_pointers[vch][i-lendelta])
437 								{
438 								memcpy(lt->value[idx]+i,  b->string_pointers[vch]+i-lendelta, lt->len[idx]-i);
439 								uniq = 1;
440 								}
441 							}
442 						}
443 					else
444 						{
445 						fprintf(stderr, LXT2_RDLOAD"Internal error "LXT2_RD_LD" ('%s') vs %d ('%s')\n",
446 							lt->len[idx], lt->value[idx],
447 							b->string_lens[vch], b->string_pointers[vch]);
448 						exit(255);
449 						}
450 
451 					break;
452 		}
453 
454 
455 	/* this string is unique if uniq != 0 */
456 	/* fprintf(stderr, LXT2_RDLOAD"%lld : [%d] '%s'\n", lt->time_table[which_time], idx, lt->value[idx]); */
457 fini:	if(uniq)
458 		{
459 		if(lt->time_table[which_time] != lt->prev_time)
460 			{
461 			lt->prev_time = lt->time_table[which_time];
462 			}
463 
464 		lt->value_change_callback(&lt, &lt->time_table[which_time], &idx, &lt->value[idx]);
465 		}
466 }
467 
468 
469 /*
470  * radix sort the fac entries based upon their first entry in the
471  * time change table.  this runs in strict linear time: we can
472  * do this because of the limited domain of the dataset.
473  */
lxt2_rd_build_radix(struct lxt2_rd_trace * lt,struct lxt2_rd_block * b,int granule,lxtint32_t strtfac,lxtint32_t endfac)474 static void lxt2_rd_build_radix(struct lxt2_rd_trace *lt, struct lxt2_rd_block *b, int granule,
475 		lxtint32_t strtfac, lxtint32_t endfac)
476 {
477 lxtint32_t i;
478 int offset;
479 
480 for(i=0;i<LXT2_RD_GRANULE_SIZE+1;i++)	/* +1 because tzc returns 33/65 when its arg == 0 */
481 	{
482 	lt->radix_sort[i] = NULL;	/* each one is a linked list: we get fac number based on address of item from lt->next_radix */
483 	}
484 
485 for(i=strtfac;i<endfac;i++)
486 	{
487 	granmsk_t x;
488 	int process_idx = i/8;
489 	int process_bit = i&7;
490 
491 	if(lt->process_mask[process_idx]&(1<<process_bit))
492 		{
493 		if((x=lt->fac_map[i]))
494 			{
495 			if((!granule)&&(x&LXT2_RD_GRAN_1VAL))
496 				{
497 				lxt2_rd_iter_radix0(lt, b, i);		/* emit vcd only if it's unique */
498 				x&=(~LXT2_RD_GRAN_1VAL);		/* clear out least sig bit */
499 				lt->fac_map[i] = x;
500 				if(!x) continue;
501 				}
502 
503 			offset = lxt2_rd_tzc(x);			/* get "which time" bucket number of new least sig one bit */
504 			lt->next_radix[i] = lt->radix_sort[offset];	/* insert item into head of radix sorted "which time" buckets */
505 			lt->radix_sort[offset] = &lt->next_radix[i];
506 			}
507 		}
508 	}
509 }
510 
511 /****************************************************************************/
512 
513 /*
514  * build compressed process mask if necessary
515  */
lxt2_rd_regenerate_process_mask(struct lxt2_rd_trace * lt)516 static void lxt2_rd_regenerate_process_mask(struct lxt2_rd_trace *lt)
517 {
518 lxtint32_t i;
519 int j, lim, idx;
520 
521 if((lt)&&(lt->process_mask_dirty))
522 	{
523 	lt->process_mask_dirty = 0;
524 	idx=0;
525 	for(i=0;i<lt->numrealfacs;i+=LXT2_RD_PARTIAL_SIZE)
526 		{
527 		if(i+LXT2_RD_PARTIAL_SIZE>lt->numrealfacs)
528 			{
529 			lim = lt->numrealfacs;
530 			}
531 			else
532 			{
533 			lim = i+LXT2_RD_PARTIAL_SIZE;
534 			}
535 
536 		lt->process_mask_compressed[idx] = 0;
537 		for(j=i;j<lim;j++)
538 			{
539 			int process_idx = j/8;		/* no need to optimize this */
540 			int process_bit = j&7;
541 
542 			if(lt->process_mask[process_idx]&(1<<process_bit))
543 				{
544 				lt->process_mask_compressed[idx] = 1;
545 				break;
546 				}
547 			}
548 
549 		idx++;
550 		}
551 	}
552 }
553 
554 /****************************************************************************/
555 
556 
557 /*
558  * process a single block and execute the vch callback as necessary
559  */
lxt2_rd_process_block(struct lxt2_rd_trace * lt,struct lxt2_rd_block * b)560 int lxt2_rd_process_block(struct lxt2_rd_trace *lt, struct lxt2_rd_block *b)
561 {
562 char vld;
563 char *pnt;
564 lxtint32_t i;
565 int granule = 0;
566 char sect_typ;
567 lxtint32_t strtfac_gran=0;
568 char granvld=0;
569 
570 b->num_map_entries = lxt2_rd_get_32(b->mem, b->uncompressed_siz - 4);
571 b->num_dict_entries = lxt2_rd_get_32(b->mem, b->uncompressed_siz - 12);
572 
573 #if LXT2_RD_GRANULE_SIZE > 32
574 if(lt->granule_size==LXT2_RD_GRANULE_SIZE)
575 	{
576 	b->map_start = (b->mem + b->uncompressed_siz - 12) - sizeof(granmsk_t) * b->num_map_entries;
577 	}
578 	else
579 	{
580 	b->map_start = (b->mem + b->uncompressed_siz - 12) - sizeof(granmsk_smaller_t) * b->num_map_entries;
581 	}
582 
583 #else
584 	b->map_start = (b->mem + b->uncompressed_siz - 12) - sizeof(granmsk_t) * b->num_map_entries;
585 #endif
586 
587 b->dict_start = b->map_start - lxt2_rd_get_32(b->mem, b->uncompressed_siz - 8);
588 
589 /* fprintf(stderr, LXT2_RDLOAD"num_map_entries: %d, num_dict_entries: %d, map_start: %08x, dict_start: %08x, mem: %08x end: %08x\n",
590 	b->num_map_entries, b->num_dict_entries, b->map_start, b->dict_start, b->mem, b->mem+b->uncompressed_siz); */
591 
592 vld = lxt2_rd_get_byte(b->dict_start - 1, 0);
593 if(vld != LXT2_RD_GRAN_SECT_DICT)
594 	{
595 	fprintf(stderr, LXT2_RDLOAD"Malformed section\n");
596 	exit(255);
597 	}
598 
599 if(b->num_dict_entries)
600 	{
601 	b->string_pointers = malloc(b->num_dict_entries * sizeof(char *));
602 	b->string_lens = malloc(b->num_dict_entries * sizeof(unsigned int));
603 	pnt = b->dict_start;
604 	for(i=0;i<b->num_dict_entries;i++)
605 		{
606 		b->string_pointers[i] = pnt;
607 		b->string_lens[i] = strlen(pnt);
608 		pnt += (b->string_lens[i] + 1);
609 		/* fprintf(stderr, LXT2_RDLOAD"%d '%s'\n", i, b->string_pointers[i]); */
610 		}
611 
612 	if(pnt!=b->map_start)
613 		{
614 		fprintf(stderr, LXT2_RDLOAD"dictionary corrupt, exiting\n");
615 		exit(255);
616 		}
617 	}
618 
619 pnt = b->mem;
620 while(((sect_typ=*pnt) == LXT2_RD_GRAN_SECT_TIME)||(sect_typ == LXT2_RD_GRAN_SECT_TIME_PARTIAL))
621 	{
622 	lxtint32_t strtfac, endfac;
623 
624 	if(sect_typ == LXT2_RD_GRAN_SECT_TIME_PARTIAL)
625 		{
626 		lxtint32_t sublen;
627 
628 		lxt2_rd_regenerate_process_mask(lt);
629 
630 		strtfac = lxt2_rd_get_32(pnt, 1);
631 		sublen = lxt2_rd_get_32(pnt, 5);
632 
633 		if(!granvld)
634 			{
635 			granvld=1;
636 			strtfac_gran = strtfac;
637 			}
638 		else
639 			{
640 			granule += (strtfac==strtfac_gran);
641 			}
642 
643 		if(!lt->process_mask_compressed[strtfac/LXT2_RD_PARTIAL_SIZE])
644 			{
645 			/* fprintf(stderr, "skipping group %d for %d bytes\n", strtfac, sublen); */
646 			pnt += 9;
647 			pnt += sublen;
648 			continue;
649 			}
650 
651 		/* fprintf(stderr, "processing group %d for %d bytes\n", strtfac, sublen); */
652 		endfac=strtfac+LXT2_RD_PARTIAL_SIZE;
653 		if(endfac>lt->numrealfacs) endfac=lt->numrealfacs;
654 		pnt += 8;
655 		}
656 		else
657 		{
658 		strtfac=0;
659 		endfac=lt->numrealfacs;
660 		}
661 
662 	/* fprintf(stderr, LXT2_RDLOAD"processing granule %d\n", granule); */
663 	pnt++;
664 	lt->num_time_table_entries = lxt2_rd_get_byte(pnt, 0);
665 	pnt++;
666 	for(i=0;i<lt->num_time_table_entries;i++)
667 		{
668 		lt->time_table[i] = lxt2_rd_get_64(pnt, 0);
669 		pnt+=8;
670 		/* fprintf(stderr, LXT2_RDLOAD"\t%d) %lld\n", i, lt->time_table[i]); */
671 		}
672 
673 	lt->fac_map_index_width = lxt2_rd_get_byte(pnt, 0);
674 	if((!lt->fac_map_index_width)||(lt->fac_map_index_width > 4))
675 		{
676 		fprintf(stderr, LXT2_RDLOAD"Map index width of %d is illegal, exiting.\n", lt->fac_map_index_width);
677 		exit(255);
678 		}
679 	pnt++;
680 
681 	for(i=strtfac;i<endfac;i++)
682 		{
683 		lxtint32_t mskindx;
684 
685 		switch(lt->fac_map_index_width)
686 			{
687 			case 1: mskindx = lxt2_rd_get_byte(pnt, 0); break;
688 			case 2: mskindx = lxt2_rd_get_16(pnt, 0); break;
689 			case 3: mskindx = lxt2_rd_get_24(pnt, 0); break;
690 			case 4:
691 			default:
692 				mskindx = lxt2_rd_get_32(pnt, 0); break;
693 			}
694 
695 		pnt += lt->fac_map_index_width;
696 
697 #if LXT2_RD_GRANULE_SIZE > 32
698 		if(lt->granule_size==LXT2_RD_GRANULE_SIZE)
699 			{
700 			lt->fac_map[i] = get_fac_msk(b->map_start, mskindx * sizeof(granmsk_t));
701 			}
702 			else
703 			{
704 			lt->fac_map[i] = get_fac_msk_smaller(b->map_start, mskindx * sizeof(granmsk_smaller_t));
705 			}
706 #else
707 		lt->fac_map[i] = get_fac_msk(b->map_start, mskindx * sizeof(granmsk_t));
708 #endif
709 		}
710 
711 	lt->fac_curpos_width = lxt2_rd_get_byte(pnt, 0);
712 	if((!lt->fac_curpos_width)||(lt->fac_curpos_width > 4))
713 		{
714 		fprintf(stderr, LXT2_RDLOAD"Curpos index width of %d is illegal, exiting.\n", lt->fac_curpos_width);
715 		exit(255);
716 		}
717 	pnt++;
718 
719 	for(i=strtfac;i<endfac;i++)
720 		{
721 		lt->fac_curpos[i] = pnt;
722 		if(lt->fac_map[i])
723 			{
724 			pnt += (lxt2_rd_ones_cnt(lt->fac_map[i]) * lt->fac_curpos_width);
725 			}
726 		}
727 
728 	lxt2_rd_build_radix(lt, b, granule, strtfac, endfac);
729 	lxt2_rd_iter_radix(lt, b);
730 
731 	if(sect_typ != LXT2_RD_GRAN_SECT_TIME_PARTIAL)
732 		{
733 		granule++;
734 		}
735 	}
736 
737 return(1);
738 }
739 
740 
741 /****************************************************************************/
742 
743 /*
744  * null callback used when a user passes NULL as an argument to lxt2_rd_iter_blocks()
745  */
lxt2_rd_null_callback(struct lxt2_rd_trace ** lt,lxtint64_t * pnt_time,lxtint32_t * pnt_facidx,char ** pnt_value)746 void lxt2_rd_null_callback(struct lxt2_rd_trace **lt, lxtint64_t *pnt_time, lxtint32_t *pnt_facidx, char **pnt_value)
747 {
748 (void) lt;
749 (void) pnt_time;
750 (void) pnt_facidx;
751 (void) pnt_value;
752 
753 /* fprintf(stderr, LXT2_RDLOAD"%lld %d %s\n", *pnt_time, *pnt_facidx, *pnt_value); */
754 }
755 
756 /****************************************************************************/
757 
758 /*
759  * initialize the trace, get compressed facnames, get geometries,
760  * and get block offset/size/timestart/timeend...
761  */
lxt2_rd_init(const char * name)762 struct lxt2_rd_trace *lxt2_rd_init(const char *name)
763 {
764 struct lxt2_rd_trace *lt=(struct lxt2_rd_trace *)calloc(1, sizeof(struct lxt2_rd_trace));
765 lxtint32_t i;
766 
767 if(!(lt->handle=fopen(name, "rb")))
768         {
769 	lxt2_rd_close(lt);
770         lt=NULL;
771         }
772         else
773 	{
774 	lxtint16_t id = 0, version = 0;
775 
776 	lt->block_mem_max = LXT2_RD_MAX_BLOCK_MEM_USAGE;    /* cutoff after this number of bytes and force flush */
777 
778 	setvbuf(lt->handle, (char *)NULL, _IONBF, 0);	/* keeps gzip from acting weird in tandem with fopen */
779 
780 	if(!fread(&id, 2, 1, lt->handle)) { id = 0; }
781 	if(!fread(&version, 2, 1, lt->handle)) { id = 0; }
782 	if(!fread(&lt->granule_size, 1, 1, lt->handle)) { id = 0; }
783 
784 	if(lxt2_rd_get_16(&id,0) != LXT2_RD_HDRID)
785 		{
786 		fprintf(stderr, LXT2_RDLOAD"*** Not an lxt file ***\n");
787 		lxt2_rd_close(lt);
788 	        lt=NULL;
789 		}
790 	else
791 	if((version=lxt2_rd_get_16(&version,0)) > LXT2_RD_VERSION)
792 		{
793 		fprintf(stderr, LXT2_RDLOAD"*** Version %d lxt not supported ***\n", version);
794 		lxt2_rd_close(lt);
795 	        lt=NULL;
796 		}
797 	else
798 	if(lt->granule_size > LXT2_RD_GRANULE_SIZE)
799 		{
800 		fprintf(stderr, LXT2_RDLOAD"*** Granule size of %d (>%d) not supported ***\n", lt->granule_size, LXT2_RD_GRANULE_SIZE);
801 		lxt2_rd_close(lt);
802 	        lt=NULL;
803 		}
804 	else
805 		{
806 		size_t rcf;
807 		int rc;
808 		char *m;
809 		off_t pos, fend;
810 		int t;
811 		struct lxt2_rd_block *b;
812 
813 		rcf=fread(&lt->numfacs, 4, 1, lt->handle);		lt->numfacs = rcf ? lxt2_rd_get_32(&lt->numfacs,0) : 0;
814 
815                 if(!lt->numfacs)
816                         {
817                         lxtint32_t num_expansion_bytes;
818 
819                         rcf = fread(&num_expansion_bytes, 4, 1, lt->handle); num_expansion_bytes = rcf ? lxt2_rd_get_32(&num_expansion_bytes,0) : 0;
820                         rcf = fread(&lt->numfacs, 4, 1, lt->handle); lt->numfacs = rcf ? lxt2_rd_get_32(&lt->numfacs,0) : 0;
821                         if(num_expansion_bytes >= 8)
822                                 {
823                                 rcf = fread(&lt->timezero, 8, 1, lt->handle); lt->timezero = rcf ? lxt2_rd_get_64(&lt->timezero,0) : 0;
824                                 if(num_expansion_bytes > 8)
825                                         {
826                                         /* future version? */
827                                         fseeko(lt->handle, num_expansion_bytes - 8, SEEK_CUR);
828                                         }
829                                 }
830                                 else
831                                 {
832                                 /* malformed */
833                                 fseeko(lt->handle, num_expansion_bytes, SEEK_CUR);
834                                 }
835                         }
836 
837 		rcf=fread(&lt->numfacbytes, 4, 1, lt->handle);		lt->numfacbytes = rcf ? lxt2_rd_get_32(&lt->numfacbytes,0) : 0;
838 		rcf=fread(&lt->longestname, 4, 1, lt->handle);		lt->longestname = rcf ? lxt2_rd_get_32(&lt->longestname,0) : 0;
839 		rcf=fread(&lt->zfacnamesize, 4, 1, lt->handle);		lt->zfacnamesize = rcf ? lxt2_rd_get_32(&lt->zfacnamesize,0) : 0;
840 		rcf=fread(&lt->zfacname_predec_size, 4, 1, lt->handle); lt->zfacname_predec_size = rcf ? lxt2_rd_get_32(&lt->zfacname_predec_size,0) : 0;
841 		rcf=fread(&lt->zfacgeometrysize, 4, 1, lt->handle);	lt->zfacgeometrysize = rcf ? lxt2_rd_get_32(&lt->zfacgeometrysize,0) : 0;
842 		rcf=fread(&lt->timescale, 1, 1, lt->handle);		if(!rcf) lt->timescale = 0; /* no swap necessary */
843 
844 		if(!lt->numfacs) /* scan-build for mallocs below */
845 			{
846 			fprintf(stderr, LXT2_RDLOAD"*** Nothing to do, zero facilities found.\n");
847 			lxt2_rd_close(lt);
848 		        lt=NULL;
849 			}
850 			else
851 			{
852 			fprintf(stderr, LXT2_RDLOAD LXT2_RD_LD" facilities\n", lt->numfacs);
853 
854 			pos = ftello(lt->handle);
855 			/* fprintf(stderr, LXT2_RDLOAD"gzip facnames start at pos %d (zsize=%d)\n", pos, lt->zfacnamesize); */
856 
857 			lt->process_mask = calloc(1, lt->numfacs/8+1);
858 			lt->process_mask_compressed = calloc(1, lt->numfacs/LXT2_RD_PARTIAL_SIZE+1);
859 
860 			lt->zhandle = gzdopen(dup(fileno(lt->handle)), "rb");
861 			m=(char *)malloc(lt->zfacname_predec_size);
862 			rc=gzread(lt->zhandle, m, lt->zfacname_predec_size);
863 			gzclose(lt->zhandle); lt->zhandle=NULL;
864 
865 			if(((lxtint32_t)rc)!=lt->zfacname_predec_size)
866 				{
867 				fprintf(stderr, LXT2_RDLOAD"*** name section mangled %d (act) vs "LXT2_RD_LD" (exp)\n", rc, lt->zfacname_predec_size);
868 				free(m);
869 
870 				lxt2_rd_close(lt);
871 			        lt=NULL;
872 				return(lt);
873 				}
874 
875 			lt->zfacnames = m;
876 
877         	        lt->faccache = calloc(1, sizeof(struct lxt2_rd_facname_cache));
878         	        lt->faccache->old_facidx = lt->numfacs;   /* causes lxt2_rd_get_facname to initialize its unroll ptr as this is always invalid */
879         	        lt->faccache->bufcurr = malloc(lt->longestname+1);
880 	                lt->faccache->bufprev = malloc(lt->longestname+1);
881 
882 			fseeko(lt->handle, pos = pos+lt->zfacnamesize, SEEK_SET);
883 			/* fprintf(stderr, LXT2_RDLOAD"seeking to geometry at %d (0x%08x)\n", pos, pos); */
884 			lt->zhandle = gzdopen(dup(fileno(lt->handle)), "rb");
885 
886 			t = lt->numfacs * 4 * sizeof(lxtint32_t);
887 			m=(char *)malloc(t);
888 			rc=gzread(lt->zhandle, m, t);
889 			gzclose(lt->zhandle); lt->zhandle=NULL;
890 			if(rc!=t)
891 				{
892 				fprintf(stderr, LXT2_RDLOAD"*** geometry section mangled %d (act) vs %d (exp)\n", rc, t);
893 				free(m);
894 
895 				lxt2_rd_close(lt);
896 			        lt=NULL;
897 				return(lt);
898 				}
899 
900 			pos = pos+lt->zfacgeometrysize;
901 
902 			lt->rows = malloc(lt->numfacs * sizeof(lxtint32_t));
903 			lt->msb = malloc(lt->numfacs * sizeof(lxtsint32_t));
904 			lt->lsb = malloc(lt->numfacs * sizeof(lxtsint32_t));
905 			lt->flags = malloc(lt->numfacs * sizeof(lxtint32_t));
906 			lt->len = malloc(lt->numfacs * sizeof(lxtint32_t));
907 			lt->value = malloc(lt->numfacs * sizeof(char *));
908 			lt->next_radix = malloc(lt->numfacs * sizeof(void *));
909 
910 			for(i=0;i<lt->numfacs;i++)
911 				{
912 				lt->rows[i] = lxt2_rd_get_32(m+i*16, 0);
913 				lt->msb[i] = lxt2_rd_get_32(m+i*16, 4);
914 				lt->lsb[i] = lxt2_rd_get_32(m+i*16, 8);
915 				lt->flags[i] = lxt2_rd_get_32(m+i*16, 12);
916 
917 				if(!(lt->flags[i] & LXT2_RD_SYM_F_INTEGER))
918 					{
919 					lt->len[i] = (lt->msb[i] <= lt->lsb[i]) ? (lt->lsb[i] - lt->msb[i] + 1) : (lt->msb[i] - lt->lsb[i] + 1);
920 					}
921 					else
922 					{
923 					lt->len[i] = 32;
924 					}
925 				lt->value[i] = calloc(lt->len[i] + 1, sizeof(char));
926 				}
927 
928 			for(lt->numrealfacs=0; lt->numrealfacs<lt->numfacs; lt->numrealfacs++)
929 				{
930 				if(lt->flags[lt->numrealfacs] & LXT2_RD_SYM_F_ALIAS)
931 					{
932 					break;
933 					}
934 				}
935 			if(lt->numrealfacs > lt->numfacs) lt->numrealfacs = lt->numfacs;
936 
937 			lt->prev_time = ~(LXT2_RD_GRAN_0VAL);
938 			free(m);
939 
940 			lt->fac_map = malloc(lt->numfacs * sizeof(granmsk_t));
941 			lt->fac_curpos = malloc(lt->numfacs * sizeof(char *));
942 
943 			for(;;)
944 				{
945 				fseeko(lt->handle, 0L, SEEK_END);
946 				fend=ftello(lt->handle);
947 				if(pos>=fend) break;
948 
949 				fseeko(lt->handle, pos, SEEK_SET);
950 				/* fprintf(stderr, LXT2_RDLOAD"seeking to block at %d (0x%08x)\n", pos, pos); */
951 
952 				b=calloc(1, sizeof(struct lxt2_rd_block));
953 
954 				rcf = fread(&b->uncompressed_siz, 4, 1, lt->handle);	b->uncompressed_siz = rcf ? lxt2_rd_get_32(&b->uncompressed_siz,0) : 0;
955 				rcf = fread(&b->compressed_siz, 4, 1, lt->handle);	b->compressed_siz = rcf ? lxt2_rd_get_32(&b->compressed_siz,0) : 0;
956 				rcf = fread(&b->start, 8, 1, lt->handle);		b->start = rcf ? lxt2_rd_get_64(&b->start,0) : 0;
957 				rcf = fread(&b->end, 8, 1, lt->handle);			b->end = rcf ? lxt2_rd_get_64(&b->end,0) : 0;
958 				pos = ftello(lt->handle);
959 				fseeko(lt->handle, pos, SEEK_SET);
960 				/* fprintf(stderr, LXT2_RDLOAD"block gzip start at pos %d (0x%08x)\n", pos, pos); */
961 				if(pos>=fend)
962 					{
963 					free(b);
964 					break;
965 					}
966 
967 				b->filepos = pos; /* mark startpos for later in case we purge it from memory */
968 				/* fprintf(stderr, LXT2_RDLOAD"un/compressed size: %d/%d\n", b->uncompressed_siz, b->compressed_siz); */
969 
970 				if((b->uncompressed_siz)&&(b->compressed_siz)&&(b->end))
971 					{
972 					/* fprintf(stderr, LXT2_RDLOAD"block [%d] %lld / %lld\n", lt->numblocks, b->start, b->end); */
973 					fseeko(lt->handle, b->compressed_siz, SEEK_CUR);
974 
975 					lt->numblocks++;
976 					if(lt->block_curr)
977 						{
978 						lt->block_curr->next = b;
979 						lt->block_curr = b;
980 						lt->end = b->end;
981 						}
982 						else
983 						{
984 						lt->block_head = lt->block_curr = b;
985 						lt->start = b->start;
986 						lt->end = b->end;
987 						}
988 					}
989 					else
990 					{
991 					free(b);
992 					break;
993 					}
994 
995 				pos+=b->compressed_siz;
996 				}
997 
998 			if(lt->numblocks)
999 				{
1000 				fprintf(stderr, LXT2_RDLOAD"Read %d block header%s OK\n", lt->numblocks, (lt->numblocks!=1) ? "s" : "");
1001 
1002 				fprintf(stderr, LXT2_RDLOAD"["LXT2_RD_LLD"] start time\n", lt->start);
1003 				fprintf(stderr, LXT2_RDLOAD"["LXT2_RD_LLD"] end time\n", lt->end);
1004 				fprintf(stderr, LXT2_RDLOAD"\n");
1005 
1006 				lt->value_change_callback = lxt2_rd_null_callback;
1007 				}
1008 				else
1009 				{
1010 				lxt2_rd_close(lt);
1011 				lt=NULL;
1012 				}
1013 			}
1014 		}
1015 	}
1016 
1017 return(lt);
1018 }
1019 
1020 
1021 /*
1022  * free up/deallocate any resources still left out there:
1023  * blindly do it based on NULL pointer comparisons (ok, since
1024  * calloc() is used to allocate all structs) as performance
1025  * isn't an issue for this set of cleanup code
1026  */
lxt2_rd_close(struct lxt2_rd_trace * lt)1027 void lxt2_rd_close(struct lxt2_rd_trace *lt)
1028 {
1029 if(lt)
1030 	{
1031 	struct lxt2_rd_block *b, *bt;
1032 	lxtint32_t i;
1033 
1034 	if(lt->process_mask) { free(lt->process_mask); lt->process_mask=NULL; }
1035 	if(lt->process_mask_compressed) { free(lt->process_mask_compressed); lt->process_mask_compressed=NULL; }
1036 
1037 	if(lt->rows) { free(lt->rows); lt->rows=NULL; }
1038 	if(lt->msb) { free(lt->msb); lt->msb=NULL; }
1039 	if(lt->lsb) { free(lt->lsb); lt->lsb=NULL; }
1040 	if(lt->flags) { free(lt->flags); lt->flags=NULL; }
1041 	if(lt->len) { free(lt->len); lt->len=NULL; }
1042 	if(lt->next_radix) { free(lt->next_radix); lt->next_radix=NULL; }
1043 
1044 	for(i=0;i<lt->numfacs;i++)
1045 		{
1046 		if(lt->value[i])
1047 			{
1048 			free(lt->value[i]); lt->value[i]=NULL;
1049 			}
1050 		}
1051 
1052 	if(lt->value) { free(lt->value); lt->value=NULL; }
1053 
1054 	if(lt->zfacnames) { free(lt->zfacnames); lt->zfacnames=NULL; }
1055 
1056 	if(lt->faccache)
1057 		{
1058 		if(lt->faccache->bufprev) { free(lt->faccache->bufprev); lt->faccache->bufprev=NULL; }
1059 		if(lt->faccache->bufcurr) { free(lt->faccache->bufcurr); lt->faccache->bufcurr=NULL; }
1060 
1061 		free(lt->faccache); lt->faccache=NULL;
1062 		}
1063 
1064 	if(lt->fac_map) { free(lt->fac_map); lt->fac_map=NULL; }
1065 	if(lt->fac_curpos) { free(lt->fac_curpos); lt->fac_curpos=NULL; }
1066 
1067 	b=lt->block_head;
1068 	while(b)
1069 		{
1070 		bt=b->next;
1071 
1072 		if(b->mem) { free(b->mem); b->mem=NULL; }
1073 
1074 		if(b->string_pointers) { free(b->string_pointers); b->string_pointers=NULL; }
1075 		if(b->string_lens) { free(b->string_lens); b->string_lens=NULL; }
1076 
1077 		free(b);
1078 		b=bt;
1079 		}
1080 
1081 	lt->block_head=lt->block_curr=NULL;
1082 
1083 	if(lt->zhandle) { gzclose(lt->zhandle); lt->zhandle=NULL; }
1084 	if(lt->handle) { fclose(lt->handle); lt->handle=NULL; }
1085 	free(lt);
1086 	}
1087 }
1088 
1089 /****************************************************************************/
1090 
1091 /*
1092  * return number of facs in trace
1093  */
lxt2_rd_get_num_facs(struct lxt2_rd_trace * lt)1094 _LXT2_RD_INLINE lxtint32_t lxt2_rd_get_num_facs(struct lxt2_rd_trace *lt)
1095 {
1096 return(lt ? lt->numfacs : 0);
1097 }
1098 
1099 
1100 /*
1101  * return fac geometry for a given index
1102  */
lxt2_rd_get_fac_geometry(struct lxt2_rd_trace * lt,lxtint32_t facidx)1103 struct lxt2_rd_geometry *lxt2_rd_get_fac_geometry(struct lxt2_rd_trace *lt, lxtint32_t facidx)
1104 {
1105 if((lt)&&(facidx<lt->numfacs))
1106 	{
1107 	lt->geometry.rows = lt->rows[facidx];
1108 	lt->geometry.msb = lt->msb[facidx];
1109 	lt->geometry.lsb = lt->lsb[facidx];
1110 	lt->geometry.flags = lt->flags[facidx];
1111 	lt->geometry.len = lt->len[facidx];
1112 	return(&lt->geometry);
1113 	}
1114 	else
1115 	{
1116 	return(NULL);
1117 	}
1118 }
1119 
1120 
1121 /*
1122  * return partial fac geometry for a given index
1123  */
lxt2_rd_get_fac_rows(struct lxt2_rd_trace * lt,lxtint32_t facidx)1124 _LXT2_RD_INLINE lxtint32_t lxt2_rd_get_fac_rows(struct lxt2_rd_trace *lt, lxtint32_t facidx)
1125 {
1126 if((lt)&&(facidx<lt->numfacs))
1127 	{
1128 	return(lt->rows[facidx]);
1129 	}
1130 	else
1131 	{
1132 	return(0);
1133 	}
1134 }
1135 
1136 
lxt2_rd_get_fac_msb(struct lxt2_rd_trace * lt,lxtint32_t facidx)1137 _LXT2_RD_INLINE lxtsint32_t lxt2_rd_get_fac_msb(struct lxt2_rd_trace *lt, lxtint32_t facidx)
1138 {
1139 if((lt)&&(facidx<lt->numfacs))
1140 	{
1141 	return(lt->msb[facidx]);
1142 	}
1143 	else
1144 	{
1145 	return(0);
1146 	}
1147 }
1148 
1149 
lxt2_rd_get_fac_lsb(struct lxt2_rd_trace * lt,lxtint32_t facidx)1150 _LXT2_RD_INLINE lxtsint32_t lxt2_rd_get_fac_lsb(struct lxt2_rd_trace *lt, lxtint32_t facidx)
1151 {
1152 if((lt)&&(facidx<lt->numfacs))
1153 	{
1154 	return(lt->lsb[facidx]);
1155 	}
1156 	else
1157 	{
1158 	return(0);
1159 	}
1160 }
1161 
1162 
lxt2_rd_get_fac_flags(struct lxt2_rd_trace * lt,lxtint32_t facidx)1163 _LXT2_RD_INLINE lxtint32_t lxt2_rd_get_fac_flags(struct lxt2_rd_trace *lt, lxtint32_t facidx)
1164 {
1165 if((lt)&&(facidx<lt->numfacs))
1166 	{
1167 	return(lt->flags[facidx]);
1168 	}
1169 	else
1170 	{
1171 	return(0);
1172 	}
1173 }
1174 
1175 
lxt2_rd_get_fac_len(struct lxt2_rd_trace * lt,lxtint32_t facidx)1176 _LXT2_RD_INLINE lxtint32_t lxt2_rd_get_fac_len(struct lxt2_rd_trace *lt, lxtint32_t facidx)
1177 {
1178 if((lt)&&(facidx<lt->numfacs))
1179 	{
1180 	return(lt->len[facidx]);
1181 	}
1182 	else
1183 	{
1184 	return(0);
1185 	}
1186 }
1187 
1188 
lxt2_rd_get_alias_root(struct lxt2_rd_trace * lt,lxtint32_t facidx)1189 _LXT2_RD_INLINE lxtint32_t lxt2_rd_get_alias_root(struct lxt2_rd_trace *lt, lxtint32_t facidx)
1190 {
1191 if((lt)&&(facidx<lt->numfacs))
1192 	{
1193 	while(lt->flags[facidx] & LXT2_RD_SYM_F_ALIAS)
1194 		{
1195 		facidx = lt->rows[facidx];	/* iterate to next alias */
1196 		}
1197 	return(facidx);
1198 	}
1199 	else
1200 	{
1201 	return(~((lxtint32_t)0));
1202 	}
1203 }
1204 
1205 
1206 /*
1207  * time queries
1208  */
lxt2_rd_get_start_time(struct lxt2_rd_trace * lt)1209 _LXT2_RD_INLINE lxtint64_t lxt2_rd_get_start_time(struct lxt2_rd_trace *lt)
1210 {
1211 return(lt ? lt->start : LXT2_RD_GRAN_0VAL);
1212 }
1213 
1214 
lxt2_rd_get_end_time(struct lxt2_rd_trace * lt)1215 _LXT2_RD_INLINE lxtint64_t lxt2_rd_get_end_time(struct lxt2_rd_trace *lt)
1216 {
1217 return(lt ? lt->end : LXT2_RD_GRAN_0VAL);
1218 }
1219 
1220 
lxt2_rd_get_timescale(struct lxt2_rd_trace * lt)1221 _LXT2_RD_INLINE char lxt2_rd_get_timescale(struct lxt2_rd_trace *lt)
1222 {
1223 return(lt ? lt->timescale : 0);
1224 }
1225 
1226 
lxt2_rd_get_timezero(struct lxt2_rd_trace * lt)1227 _LXT2_RD_INLINE lxtsint64_t lxt2_rd_get_timezero(struct lxt2_rd_trace *lt)
1228 {
1229 return(lt ? lt->timezero : 0);
1230 }
1231 
1232 
1233 
1234 /*
1235  * extract facname from prefix-compressed table.  this
1236  * performs best when extracting facs with monotonically
1237  * increasing indices...
1238  */
lxt2_rd_get_facname(struct lxt2_rd_trace * lt,lxtint32_t facidx)1239 char *lxt2_rd_get_facname(struct lxt2_rd_trace *lt, lxtint32_t facidx)
1240 {
1241 char *pnt;
1242 lxtint32_t clone, j;
1243 
1244 if(lt)
1245 	{
1246 	if((facidx==(lt->faccache->old_facidx+1))||(!facidx))
1247 		{
1248 		if(!facidx)
1249 			{
1250 			lt->faccache->n = lt->zfacnames;
1251 			lt->faccache->bufcurr[0] = 0;
1252 			lt->faccache->bufprev[0] = 0;
1253 			}
1254 
1255 		if(facidx!=lt->numfacs)
1256 			{
1257 			pnt = lt->faccache->bufcurr;
1258 			lt->faccache->bufcurr = lt->faccache->bufprev;
1259 			lt->faccache->bufprev = pnt;
1260 
1261 			clone=lxt2_rd_get_16(lt->faccache->n, 0);  lt->faccache->n+=2;
1262 			pnt=lt->faccache->bufcurr;
1263 
1264 			for(j=0;j<clone;j++)
1265 				{
1266 				*(pnt++) = lt->faccache->bufprev[j];
1267 				}
1268 
1269 			while((*(pnt++)=lxt2_rd_get_byte(lt->faccache->n++,0)));
1270 			lt->faccache->old_facidx = facidx;
1271 			return(lt->faccache->bufcurr);
1272 			}
1273 			else
1274 			{
1275 			return(NULL);	/* no more left */
1276 			}
1277 		}
1278 		else
1279 		{
1280 		if(facidx<lt->numfacs)
1281 			{
1282 			int strt;
1283 
1284 			if(facidx==lt->faccache->old_facidx)
1285 				{
1286 				return(lt->faccache->bufcurr);
1287 				}
1288 
1289 			if(facidx>(lt->faccache->old_facidx+1))
1290 				{
1291 				strt = lt->faccache->old_facidx+1;
1292 				}
1293 				else
1294 				{
1295 				strt=0;
1296 				}
1297 
1298 			for(j=strt;j<facidx;j++)
1299 				{
1300 				lxt2_rd_get_facname(lt, j);
1301 				}
1302 
1303 			return(lxt2_rd_get_facname(lt, j));
1304 			}
1305 		}
1306 	}
1307 
1308 return(NULL);
1309 }
1310 
1311 
1312 /*
1313  * iter mask manipulation util functions
1314  */
lxt2_rd_get_fac_process_mask(struct lxt2_rd_trace * lt,lxtint32_t facidx)1315 _LXT2_RD_INLINE int lxt2_rd_get_fac_process_mask(struct lxt2_rd_trace *lt, lxtint32_t facidx)
1316 {
1317 if(lt)
1318 	{
1319 	if(facidx<lt->numfacs)
1320 		{
1321 		int process_idx = facidx/8;
1322 		int process_bit = facidx&7;
1323 
1324 		return( (lt->process_mask[process_idx]&(1<<process_bit)) != 0 );
1325 		}
1326 	}
1327 return(0);
1328 }
1329 
1330 
lxt2_rd_set_fac_process_mask(struct lxt2_rd_trace * lt,lxtint32_t facidx)1331 _LXT2_RD_INLINE int lxt2_rd_set_fac_process_mask(struct lxt2_rd_trace *lt, lxtint32_t facidx)
1332 {
1333 int rc=0;
1334 
1335 if(lt)
1336 	{
1337 	lt->process_mask_dirty = 1;
1338 	if(facidx<lt->numfacs)
1339 		{
1340 		int idx = facidx/8;
1341 		int bitpos = facidx&7;
1342 
1343 		lt->process_mask[idx] |= (1<<bitpos);
1344 		}
1345 	rc=1;
1346 	}
1347 
1348 return(rc);
1349 }
1350 
1351 
lxt2_rd_clr_fac_process_mask(struct lxt2_rd_trace * lt,lxtint32_t facidx)1352 _LXT2_RD_INLINE int lxt2_rd_clr_fac_process_mask(struct lxt2_rd_trace *lt, lxtint32_t facidx)
1353 {
1354 int rc=0;
1355 
1356 if(lt)
1357 	{
1358 	lt->process_mask_dirty = 1;
1359 	if(facidx<lt->numfacs)
1360 		{
1361 		int idx = facidx/8;
1362 		int bitpos = facidx&7;
1363 
1364 		lt->process_mask[idx] &= (~(1<<bitpos));
1365 		}
1366 	rc=1;
1367 	}
1368 
1369 return(rc);
1370 }
1371 
1372 
lxt2_rd_set_fac_process_mask_all(struct lxt2_rd_trace * lt)1373 _LXT2_RD_INLINE int lxt2_rd_set_fac_process_mask_all(struct lxt2_rd_trace *lt)
1374 {
1375 int rc=0;
1376 
1377 if(lt)
1378 	{
1379 	lt->process_mask_dirty = 1;
1380 	memset(lt->process_mask, 0xff, (lt->numfacs+7)/8);
1381 	rc=1;
1382 	}
1383 
1384 return(rc);
1385 }
1386 
1387 
lxt2_rd_clr_fac_process_mask_all(struct lxt2_rd_trace * lt)1388 _LXT2_RD_INLINE int lxt2_rd_clr_fac_process_mask_all(struct lxt2_rd_trace *lt)
1389 {
1390 int rc=0;
1391 
1392 if(lt)
1393 	{
1394 	lt->process_mask_dirty = 1;
1395 	memset(lt->process_mask, 0x00, (lt->numfacs+7)/8);
1396 	rc=1;
1397 	}
1398 
1399 return(rc);
1400 }
1401 
1402 
1403 /*
1404  * block memory set/get used to control buffering
1405  */
lxt2_rd_set_max_block_mem_usage(struct lxt2_rd_trace * lt,lxtint64_t block_mem_max)1406 _LXT2_RD_INLINE lxtint64_t lxt2_rd_set_max_block_mem_usage(struct lxt2_rd_trace *lt, lxtint64_t block_mem_max)
1407 {
1408 lxtint64_t rc = lt->block_mem_max;
1409 lt->block_mem_max = block_mem_max;
1410 return(rc);
1411 }
1412 
1413 
lxt2_rd_get_block_mem_usage(struct lxt2_rd_trace * lt)1414 _LXT2_RD_INLINE lxtint64_t lxt2_rd_get_block_mem_usage(struct lxt2_rd_trace *lt)
1415 {
1416 return(lt->block_mem_consumed);
1417 }
1418 
1419 
1420 /*
1421  * return total number of blocks
1422  */
lxt2_rd_get_num_blocks(struct lxt2_rd_trace * lt)1423 _LXT2_RD_INLINE unsigned int lxt2_rd_get_num_blocks(struct lxt2_rd_trace *lt)
1424 {
1425 return(lt->numblocks);
1426 }
1427 
1428 /*
1429  * return number of active blocks
1430  */
lxt2_rd_get_num_active_blocks(struct lxt2_rd_trace * lt)1431 unsigned int lxt2_rd_get_num_active_blocks(struct lxt2_rd_trace *lt)
1432 {
1433 int blk=0;
1434 
1435 if(lt)
1436 	{
1437 	struct lxt2_rd_block *b = lt->block_head;
1438 
1439 	while(b)
1440 		{
1441 		if((!b->short_read_ignore)&&(!b->exclude_block))
1442 			{
1443 			blk++;
1444 			}
1445 
1446 		b=b->next;
1447 		}
1448 	}
1449 
1450 return(blk);
1451 }
1452 
1453 /****************************************************************************/
1454 
1455 /*
1456  * block iteration...purge/reload code here isn't sophisticated as it
1457  * merely caches the FIRST set of blocks which fit in lt->block_mem_max.
1458  * n.b., returns number of blocks processed
1459  */
lxt2_rd_iter_blocks(struct lxt2_rd_trace * lt,void (* value_change_callback)(struct lxt2_rd_trace ** lt,lxtint64_t * time,lxtint32_t * facidx,char ** value),void * user_callback_data_pointer)1460 int lxt2_rd_iter_blocks(struct lxt2_rd_trace *lt,
1461 	void (*value_change_callback)(struct lxt2_rd_trace **lt, lxtint64_t *time, lxtint32_t *facidx, char **value),
1462 	void *user_callback_data_pointer)
1463 {
1464 struct lxt2_rd_block *b;
1465 int blk=0, blkfinal=0;
1466 int processed = 0;
1467 struct lxt2_rd_block *bcutoff=NULL, *bfinal=NULL;
1468 int striped_kill = 0;
1469 unsigned int real_uncompressed_siz = 0;
1470 unsigned char gzid[2];
1471 lxtint32_t i;
1472 
1473 if(lt)
1474 	{
1475 	lt->value_change_callback = value_change_callback ? value_change_callback : lxt2_rd_null_callback;
1476 	lt->user_callback_data_pointer = user_callback_data_pointer;
1477 
1478 	b = lt->block_head;
1479 	blk=0;
1480 
1481 	for(i=0;i<lt->numfacs;i++)
1482 		{
1483 		if(lt->value[i]) lt->value[i][0] = 0;
1484 		}
1485 
1486 	while(b)
1487 		{
1488 		if((!b->mem)&&(!b->short_read_ignore)&&(!b->exclude_block))
1489 			{
1490 			if(processed<5)
1491 				{
1492 				int gate = (processed==4) && b->next;
1493 				fprintf(stderr, LXT2_RDLOAD"block [%d] processing "LXT2_RD_LLD" / "LXT2_RD_LLD"%s\n", blk, b->start, b->end, gate ? " ..." : "");
1494 				if(gate) { bcutoff = b; }
1495 				}
1496 
1497 			processed++;
1498 
1499 			fseeko(lt->handle, b->filepos, SEEK_SET);
1500 			gzid[0]=gzid[1]=0;
1501 			if(!fread(&gzid, 2, 1, lt->handle)) { gzid[0] = gzid[1] = 0; }
1502 			fseeko(lt->handle, b->filepos, SEEK_SET);
1503 
1504 			if((striped_kill = (gzid[0]!=0x1f)||(gzid[1]!=0x8b)))
1505 				{
1506 				lxtint32_t clen, unclen, iter=0;
1507 				char *pnt;
1508 				off_t fspos = b->filepos;
1509 
1510 				lxtint32_t zlen = 16;
1511 				char *zbuff=malloc(zlen);
1512 				struct z_stream_s strm;
1513 
1514 				real_uncompressed_siz = b->uncompressed_siz;
1515 				pnt = b->mem = malloc(b->uncompressed_siz);
1516 				b->uncompressed_siz = 0;
1517 
1518 				lxt2_rd_regenerate_process_mask(lt);
1519 
1520 				while(iter!=0xFFFFFFFF)
1521 					{
1522 					size_t rcf;
1523 
1524 					clen = unclen = iter = 0;
1525 					rcf = fread(&clen, 4, 1, lt->handle);	clen = rcf ? lxt2_rd_get_32(&clen,0) : 0;
1526 					rcf = fread(&unclen, 4, 1, lt->handle);	unclen = rcf ? lxt2_rd_get_32(&unclen,0) : 0;
1527 					rcf = fread(&iter, 4, 1, lt->handle);	iter = rcf ? lxt2_rd_get_32(&iter,0) : 0;
1528 
1529 					fspos += 12;
1530 					if((iter==0xFFFFFFFF)||(lt->process_mask_compressed[iter/LXT2_RD_PARTIAL_SIZE]))
1531 						{
1532 						if(clen > zlen)
1533 							{
1534 							if(zbuff) free(zbuff);
1535 							zlen = clen * 2;
1536 							zbuff = malloc(zlen ? zlen : 1 /* scan-build */);
1537 							}
1538 
1539 						if(!fread(zbuff, clen, 1, lt->handle)) { clen = 0; }
1540 
1541 						strm.avail_in = clen-10;
1542 						strm.avail_out = unclen;
1543 						strm.total_in = strm.total_out = 0;
1544 						strm.zalloc = NULL; strm.zfree = NULL; strm.opaque = NULL;
1545 						strm.next_in = (unsigned char *)(zbuff+10);
1546 						strm.next_out = (unsigned char *)(pnt);
1547 
1548 						if((clen != 0)&&(unclen != 0))
1549 							{
1550 							inflateInit2(&strm, -MAX_WBITS);
1551 							while (Z_OK ==  inflate(&strm, Z_NO_FLUSH));
1552 							inflateEnd(&strm);
1553 							}
1554 
1555 						if((strm.total_out!=unclen)||(clen == 0)||(unclen == 0))
1556 							{
1557 							fprintf(stderr, LXT2_RDLOAD"short read on subblock %ld vs "LXT2_RD_LD" (exp), ignoring\n", strm.total_out, unclen);
1558 							free(b->mem); b->mem=NULL;
1559 							b->short_read_ignore = 1;
1560 							b->uncompressed_siz = real_uncompressed_siz;
1561 							break;
1562 							}
1563 
1564 						b->uncompressed_siz+=strm.total_out;
1565 						pnt += strm.total_out;
1566 						fspos += clen;
1567 						}
1568 						else
1569 						{
1570 						fspos += clen;
1571 						fseeko(lt->handle, fspos, SEEK_SET);
1572 						}
1573 					}
1574 
1575 
1576 				if(zbuff) free(zbuff);
1577 				}
1578 				else
1579 				{
1580 				int rc;
1581 
1582 				b->mem = malloc(b->uncompressed_siz);
1583 				lt->zhandle = gzdopen(dup(fileno(lt->handle)), "rb");
1584 				rc=gzread(lt->zhandle, b->mem, b->uncompressed_siz);
1585 				gzclose(lt->zhandle); lt->zhandle=NULL;
1586 				if(((lxtint32_t)rc)!=b->uncompressed_siz)
1587 					{
1588 					fprintf(stderr, LXT2_RDLOAD"short read on block %d vs "LXT2_RD_LD" (exp), ignoring\n", rc, b->uncompressed_siz);
1589 					free(b->mem); b->mem=NULL;
1590 					b->short_read_ignore = 1;
1591 					}
1592 					else
1593 					{
1594 					lt->block_mem_consumed += b->uncompressed_siz;
1595 					}
1596 				}
1597 
1598 			bfinal=b;
1599 			blkfinal = blk;
1600 			}
1601 
1602 		if(b->mem)
1603 			{
1604 			lxt2_rd_process_block(lt, b);
1605 
1606 			if(striped_kill)
1607 				{
1608 				free(b->mem); b->mem=NULL;
1609 				b->uncompressed_siz = real_uncompressed_siz;
1610 				}
1611 			else
1612 			if(lt->numblocks > 1)	/* no sense freeing up the single block case */
1613 				{
1614 				if(lt->block_mem_consumed > lt->block_mem_max)
1615 					{
1616 					lt->block_mem_consumed -= b->uncompressed_siz;
1617 					free(b->mem); b->mem=NULL;
1618 					}
1619 				}
1620 			}
1621 
1622 		blk++;
1623 		b=b->next;
1624 		}
1625 	}
1626 
1627 if((bcutoff)&&(bfinal!=bcutoff))
1628 	{
1629 	fprintf(stderr, LXT2_RDLOAD"block [%d] processed "LXT2_RD_LLD" / "LXT2_RD_LLD"\n", blkfinal, bfinal->start, bfinal->end);
1630 	}
1631 
1632 return(blk);
1633 }
1634 
1635 
1636 /*
1637  * callback access to the user callback data pointer (if required)
1638  */
lxt2_rd_get_user_callback_data_pointer(struct lxt2_rd_trace * lt)1639 _LXT2_RD_INLINE void *lxt2_rd_get_user_callback_data_pointer(struct lxt2_rd_trace *lt)
1640 {
1641 if(lt)
1642 	{
1643 	return(lt->user_callback_data_pointer);
1644 	}
1645 	else
1646 	{
1647 	return(NULL);
1648 	}
1649 }
1650 
1651 
1652 /*
1653  * limit access to certain timerange in file
1654  * and return number of active blocks
1655  */
lxt2_rd_limit_time_range(struct lxt2_rd_trace * lt,lxtint64_t strt_time,lxtint64_t end_time)1656 unsigned int lxt2_rd_limit_time_range(struct lxt2_rd_trace *lt, lxtint64_t strt_time, lxtint64_t end_time)
1657 {
1658 lxtint64_t tmp_time;
1659 int blk=0;
1660 
1661 if(lt)
1662 	{
1663 	struct lxt2_rd_block *b = lt->block_head;
1664 	struct lxt2_rd_block *bprev = NULL;
1665 	int state = 0;
1666 
1667 	if(strt_time > end_time)
1668 		{
1669 		tmp_time = strt_time;
1670 		strt_time = end_time;
1671 		end_time = tmp_time;
1672 		}
1673 
1674 	while(b)
1675 		{
1676 		switch(state)
1677 			{
1678 			case 0: if(b->end >= strt_time)
1679 					{
1680 					state = 1;
1681 					if((b->start > strt_time) && (bprev))
1682 						{
1683 						bprev->exclude_block = 0;
1684 						blk++;
1685 						}
1686 					}
1687 				break;
1688 
1689 			case 1: if(b->start > end_time) state = 2;
1690 				break;
1691 
1692 			default: break;
1693 			}
1694 
1695 		if((state==1) && (!b->short_read_ignore))
1696 			{
1697 			b->exclude_block = 0;
1698 			blk++;
1699 			}
1700 			else
1701 			{
1702 			b->exclude_block = 1;
1703 			}
1704 
1705 		bprev = b;
1706 		b = b->next;
1707 		}
1708 
1709 	}
1710 
1711 return(blk);
1712 }
1713 
1714 /*
1715  * unrestrict access to the whole file
1716  * and return number of active blocks
1717  */
lxt2_rd_unlimit_time_range(struct lxt2_rd_trace * lt)1718 unsigned int lxt2_rd_unlimit_time_range(struct lxt2_rd_trace *lt)
1719 {
1720 int blk=0;
1721 
1722 if(lt)
1723 	{
1724 	struct lxt2_rd_block *b = lt->block_head;
1725 
1726 	while(b)
1727 		{
1728 		b->exclude_block = 0;
1729 
1730 		if(!b->short_read_ignore)
1731 			{
1732 			blk++;
1733 			}
1734 
1735 		b=b->next;
1736 		}
1737 	}
1738 
1739 return(blk);
1740 }
1741 
1742