1 /*
2  * Copyright (c) Tony Bybell 1999-2018.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  */
9 
10 #include "globals.h"
11 #include <config.h>
12 #include "analyzer.h"
13 #include "currenttime.h"
14 #include "symbol.h"
15 #include "bsearch.h"
16 #include "strace.h"
17 #include "hierpack.h"
18 #include <ctype.h>
19 
compar_timechain(const void * s1,const void * s2)20 static int compar_timechain(const void *s1, const void *s2)
21 {
22 TimeType key, obj, delta;
23 TimeType *cpos;
24 int rv;
25 
26 key=*((TimeType *)s1);
27 obj=*(cpos=(TimeType *)s2);
28 
29 if((obj<=key)&&(obj>GLOBALS->max_compare_time_tc_bsearch_c_1))
30 	{
31 	GLOBALS->max_compare_time_tc_bsearch_c_1=obj;
32 	GLOBALS->max_compare_pos_tc_bsearch_c_1=cpos;
33 	}
34 
35 delta=key-obj;
36 if(delta<0) rv=-1;
37 else if(delta>0) rv=1;
38 else rv=0;
39 
40 return(rv);
41 }
42 
bsearch_timechain(TimeType key)43 int bsearch_timechain(TimeType key)
44 {
45 GLOBALS->max_compare_time_tc_bsearch_c_1=-2; GLOBALS->max_compare_pos_tc_bsearch_c_1=NULL;
46 
47 if(!GLOBALS->strace_ctx->timearray) return(-1);
48 
49 if(bsearch(&key, GLOBALS->strace_ctx->timearray, GLOBALS->strace_ctx->timearray_size, sizeof(TimeType), compar_timechain))
50         {
51         /* nothing, all side effects are in bsearch */
52         }
53 
54 if((!GLOBALS->max_compare_pos_tc_bsearch_c_1)||(GLOBALS->max_compare_time_tc_bsearch_c_1<GLOBALS->shift_timebase))
55 	{
56 	GLOBALS->max_compare_pos_tc_bsearch_c_1=GLOBALS->strace_ctx->timearray; /* aix bsearch fix */
57 	}
58 
59 return(GLOBALS->max_compare_pos_tc_bsearch_c_1-GLOBALS->strace_ctx->timearray);
60 }
61 
62 /*****************************************************************************************/
63 
bsearch_aetinfo_timechain(TimeType key)64 int bsearch_aetinfo_timechain(TimeType key)
65 {
66 GLOBALS->max_compare_time_tc_bsearch_c_1=-2; GLOBALS->max_compare_pos_tc_bsearch_c_1=NULL;
67 
68 if(!GLOBALS->ae2_time_xlate) return(-1);
69 
70 if(bsearch(&key, GLOBALS->ae2_time_xlate, GLOBALS->ae2_end_cyc - GLOBALS->ae2_start_cyc + 1, sizeof(TimeType), compar_timechain))
71         {
72         /* nothing, all side effects are in bsearch */
73         }
74 
75 if(!GLOBALS->max_compare_pos_tc_bsearch_c_1)
76 	{
77 	GLOBALS->max_compare_pos_tc_bsearch_c_1=GLOBALS->ae2_time_xlate; /* aix bsearch fix */
78 	}
79 
80 return(GLOBALS->max_compare_pos_tc_bsearch_c_1-GLOBALS->ae2_time_xlate);
81 }
82 
83 /*****************************************************************************************/
84 
compar_histent(const void * s1,const void * s2)85 static int compar_histent(const void *s1, const void *s2)
86 {
87 TimeType key, obj, delta;
88 hptr cpos;
89 int rv;
90 
91 key=*((TimeType *)s1);
92 obj=(cpos=(*((hptr *)s2)))->time;
93 
94 if((obj<=key)&&(obj>GLOBALS->max_compare_time_bsearch_c_1))
95 	{
96 	GLOBALS->max_compare_time_bsearch_c_1=obj;
97 	GLOBALS->max_compare_pos_bsearch_c_1=cpos;
98 	GLOBALS->max_compare_index=(hptr *)s2;
99 	}
100 
101 delta=key-obj;
102 if(delta<0) rv=-1;
103 else if(delta>0) rv=1;
104 else rv=0;
105 
106 return(rv);
107 }
108 
bsearch_node(nptr n,TimeType key)109 hptr bsearch_node(nptr n, TimeType key)
110 {
111 GLOBALS->max_compare_time_bsearch_c_1=-2; GLOBALS->max_compare_pos_bsearch_c_1=NULL; GLOBALS->max_compare_index=NULL;
112 
113 if(bsearch(&key, n->harray, n->numhist, sizeof(hptr), compar_histent))
114         {
115         /* nothing, all side effects are in bsearch */
116         }
117 
118 if((!GLOBALS->max_compare_pos_bsearch_c_1)||(GLOBALS->max_compare_time_bsearch_c_1<LLDescriptor(0)))
119 	{
120 	GLOBALS->max_compare_pos_bsearch_c_1=n->harray[1]; /* aix bsearch fix */
121 	GLOBALS->max_compare_index=&(n->harray[1]);
122 	}
123 
124 while(GLOBALS->max_compare_pos_bsearch_c_1->next) /* non-RoSync dumper deglitching fix */
125 	{
126 	if(GLOBALS->max_compare_pos_bsearch_c_1->time != GLOBALS->max_compare_pos_bsearch_c_1->next->time) break;
127 	GLOBALS->max_compare_pos_bsearch_c_1 = GLOBALS->max_compare_pos_bsearch_c_1->next;
128 	}
129 
130 return(GLOBALS->max_compare_pos_bsearch_c_1);
131 }
132 
133 /*****************************************************************************************/
134 
135 
compar_vectorent(const void * s1,const void * s2)136 static int compar_vectorent(const void *s1, const void *s2)
137 {
138 TimeType key, obj, delta;
139 vptr cpos;
140 int rv;
141 
142 key=*((TimeType *)s1);
143 /* obj=(cpos=(*((vptr *)s2)))->time+GLOBALS->shift_timebase; */
144 
145 obj=(cpos=(*((vptr *)s2)))->time;
146 
147 if((obj<=key)&&(obj>GLOBALS->vmax_compare_time_bsearch_c_1))
148 	{
149 	GLOBALS->vmax_compare_time_bsearch_c_1=obj;
150 	GLOBALS->vmax_compare_pos_bsearch_c_1=cpos;
151         GLOBALS->vmax_compare_index=(vptr *)s2;
152 	}
153 
154 delta=key-obj;
155 if(delta<0) rv=-1;
156 else if(delta>0) rv=1;
157 else rv=0;
158 
159 return(rv);
160 }
161 
bsearch_vector(bvptr b,TimeType key)162 vptr bsearch_vector(bvptr b, TimeType key)
163 {
164 GLOBALS->vmax_compare_time_bsearch_c_1=-2; GLOBALS->vmax_compare_pos_bsearch_c_1=NULL; GLOBALS->vmax_compare_index=NULL;
165 
166 if(bsearch(&key, b->vectors, b->numregions, sizeof(vptr), compar_vectorent))
167         {
168         /* nothing, all side effects are in bsearch */
169         }
170 
171 if((!GLOBALS->vmax_compare_pos_bsearch_c_1)||(GLOBALS->vmax_compare_time_bsearch_c_1<LLDescriptor(0)))
172 	{
173 	/* ignore warning: array index of '1' indexes past the end of an array (that contains 1 elements) [-Warray-bounds] */
174 	/* because this array is allocated with size > that declared in the structure definition via end of structure malloc padding */
175 	GLOBALS->vmax_compare_pos_bsearch_c_1=b->vectors[1]; /* aix bsearch fix */
176 	GLOBALS->vmax_compare_index=&(b->vectors[1]);
177 	}
178 
179 while(GLOBALS->vmax_compare_pos_bsearch_c_1->next) /* non-RoSync dumper deglitching fix */
180 	{
181 	if(GLOBALS->vmax_compare_pos_bsearch_c_1->time != GLOBALS->vmax_compare_pos_bsearch_c_1->next->time) break;
182 	GLOBALS->vmax_compare_pos_bsearch_c_1 = GLOBALS->vmax_compare_pos_bsearch_c_1->next;
183 	}
184 
185 return(GLOBALS->vmax_compare_pos_bsearch_c_1);
186 }
187 
188 /*****************************************************************************************/
189 
190 
compar_trunc(const void * s1,const void * s2)191 static int compar_trunc(const void *s1, const void *s2)
192 {
193 char *str;
194 char vcache[2];
195 int key, obj;
196 
197 str=(char *)s2;
198 key=*((int*)s1);
199 
200 vcache[0]=*str;
201 vcache[1]=*(str+1);
202 *str='+';
203 *(str+1)=0;
204 obj=font_engine_string_measure(GLOBALS->wavefont,GLOBALS->trunc_asciibase_bsearch_c_1);
205 *str=vcache[0];
206 *(str+1)=vcache[1];
207 
208 if((obj<=key)&&(obj>GLOBALS->maxlen_trunc))
209         {
210         GLOBALS->maxlen_trunc=obj;
211         GLOBALS->maxlen_trunc_pos_bsearch_c_1=str;
212         }
213 
214 return(key-obj);
215 }
216 
217 
bsearch_trunc(char * ascii,int maxlen)218 char *bsearch_trunc(char *ascii, int maxlen)
219 {
220 int len;
221 
222 if((maxlen<=0)||(!ascii)||(!(len=strlen(ascii)))) return(NULL);
223 
224 GLOBALS->maxlen_trunc_pos_bsearch_c_1=NULL;
225 
226 if(GLOBALS->wavefont->is_mono)
227 	{
228 	int adjusted_len = maxlen / GLOBALS->wavefont->mono_width;
229 	if(adjusted_len) adjusted_len--;
230 	if(GLOBALS->wavefont->mono_width <= maxlen)
231 		{
232 		GLOBALS->maxlen_trunc_pos_bsearch_c_1 = ascii + adjusted_len;
233 		}
234 	}
235 	else
236 	{
237 	GLOBALS->maxlen_trunc=0;
238 
239 	if(bsearch(&maxlen, GLOBALS->trunc_asciibase_bsearch_c_1=ascii, len, sizeof(char), compar_trunc))
240 	        {
241 	        /* nothing, all side effects are in bsearch */
242 	        }
243 	}
244 
245 return(GLOBALS->maxlen_trunc_pos_bsearch_c_1);
246 }
247 
248 
bsearch_trunc_print(char * ascii,int maxlen)249 char *bsearch_trunc_print(char *ascii, int maxlen)
250 {
251 int len;
252 
253 if((maxlen<=0)||(!ascii)||(!(len=strlen(ascii)))) return(NULL);
254 
255 GLOBALS->maxlen_trunc=0; GLOBALS->maxlen_trunc_pos_bsearch_c_1=NULL;
256 
257 if(bsearch(&maxlen, GLOBALS->trunc_asciibase_bsearch_c_1=ascii, len, sizeof(char), compar_trunc))
258         {
259 	/* nothing, all side effects are in bsearch */
260         }
261 
262 return(GLOBALS->maxlen_trunc_pos_bsearch_c_1);
263 }
264 
265 
266 /*****************************************************************************************/
267 
compar_facs(const void * key,const void * v2)268 static int compar_facs(const void *key, const void *v2)
269 {
270 struct symbol *s2;
271 int rc;
272 int was_packed = HIER_DEPACK_STATIC;
273 char *s3;
274 
275 s2=*((struct symbol **)v2);
276 s3 = hier_decompress_flagged(s2->name, &was_packed);
277 rc=sigcmp((char *)key,s3);
278 
279 /* if(was_packed) free_2(s3); ...not needed with HIER_DEPACK_STATIC */
280 
281 return(rc);
282 }
283 
bsearch_facs(char * ascii,unsigned int * rows_return)284 struct symbol *bsearch_facs(char *ascii, unsigned int *rows_return)
285 {
286 struct symbol **rc;
287 int len;
288 
289 if ((!ascii)||(!(len=strlen(ascii)))) return(NULL);
290 if(rows_return)
291 	{
292 	*rows_return = 0;
293 	}
294 
295 if(ascii[len-1]=='}')
296 	{
297 	int i;
298 
299 	for(i=len-2;i>=2;i--)
300 		{
301 		if(isdigit((int)(unsigned char)ascii[i])) continue;
302 		if(ascii[i]=='{')
303 			{
304 			char *tsc = wave_alloca(i+1);
305 			memcpy(tsc, ascii, i+1);
306 			tsc[i] = 0;
307 			rc=(struct symbol **)bsearch(tsc, GLOBALS->facs, GLOBALS->numfacs, sizeof(struct symbol *), compar_facs);
308 			if(rc)
309 				{
310 				unsigned int whichrow = atoi(&ascii[i+1]);
311 				if(rows_return) *rows_return = whichrow;
312 
313 #ifdef WAVE_ARRAY_SUPPORT
314 				if(whichrow <= (*rc)->n->array_height)
315 #endif
316 					{
317 					return(*rc);
318 					}
319 				}
320 			}
321 		break;	/* fallthrough to normal handler */
322 		}
323 
324 	}
325 
326 rc=(struct symbol **)bsearch(ascii, GLOBALS->facs, GLOBALS->numfacs, sizeof(struct symbol *), compar_facs);
327 if(rc) return(*rc); else return(NULL);
328 }
329