1 /*
2  * Copyright (c) Tony Bybell 1999-2013.
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 #include <config.h>
10 #include "globals.h"
11 #include <ctype.h>
12 #include "gtk12compat.h"
13 #include "strace.h"
14 #include "currenttime.h"
15 #include "hierpack.h"
16 
17 #define WV_STRACE_CTX "strace_ctx"
18 
19 /* need to do this every time you connect a signal */
20 #ifdef WAVE_USE_GTK2
21 #define WV_STRACE_CURWIN(x) g_object_set_data(G_OBJECT(x), WV_STRACE_CTX, (gpointer)GLOBALS->strace_ctx)
22 #else
23 #define WV_STRACE_CURWIN(x) do { } while(0 && (x))
24 #endif
25 
26 /* need to do this at top of every entry point function where a signal is connected */
27 #ifdef WAVE_USE_GTK2
28 #define GET_WV_STRACE_CURWIN(x) GLOBALS->strace_ctx=g_object_get_data(G_OBJECT(x), WV_STRACE_CTX)
29 #else
30 #define GET_WV_STRACE_CURWIN(x) do { } while(0 && (x))
31 #endif
32 
33 static char *logical[]=
34         {"AND", "OR", "XOR", "NAND", "NOR", "XNOR"};
35 
36 static char *stype[WAVE_STYPE_COUNT]=
37         {"Don't Care", "High", "Z (Mid)", "X", "Low", "String",
38          "Rising Edge", "Falling Edge", "Any Edge"};
39 
40 static struct item_mark_string item_mark_start_strings[]=
41 	{
42 	   { "Start of Time",  0 },
43 	   { "Named Marker A", 0 },
44 	   { "Named Marker B", 0 },
45 	   { "Named Marker C", 0 },
46 	   { "Named Marker D", 0 },
47 	   { "Named Marker E", 0 },
48 	   { "Named Marker F", 0 },
49 	   { "Named Marker G", 0 },
50 	   { "Named Marker H", 0 },
51 	   { "Named Marker I", 0 },
52 	   { "Named Marker J", 0 },
53 	   { "Named Marker K", 0 },
54 	   { "Named Marker L", 0 },
55 	   { "Named Marker M", 0 },
56 	   { "Named Marker N", 0 },
57 	   { "Named Marker O", 0 },
58 	   { "Named Marker P", 0 },
59 	   { "Named Marker Q", 0 },
60 	   { "Named Marker R", 0 },
61 	   { "Named Marker S", 0 },
62 	   { "Named Marker T", 0 },
63 	   { "Named Marker U", 0 },
64 	   { "Named Marker V", 0 },
65 	   { "Named Marker W", 0 },
66 	   { "Named Marker X", 0 },
67 	   { "Named Marker Y", 0 },
68 	   { "Named Marker Z", 0 }
69 	};
70 
71 static struct item_mark_string item_mark_end_strings[]=
72 	{
73 	   { "End of Time",    0 },
74 	   { "Named Marker A", 0 },
75 	   { "Named Marker B", 0 },
76 	   { "Named Marker C", 0 },
77 	   { "Named Marker D", 0 },
78 	   { "Named Marker E", 0 },
79 	   { "Named Marker F", 0 },
80 	   { "Named Marker G", 0 },
81 	   { "Named Marker H", 0 },
82 	   { "Named Marker I", 0 },
83 	   { "Named Marker J", 0 },
84 	   { "Named Marker K", 0 },
85 	   { "Named Marker L", 0 },
86 	   { "Named Marker M", 0 },
87 	   { "Named Marker N", 0 },
88 	   { "Named Marker O", 0 },
89 	   { "Named Marker P", 0 },
90 	   { "Named Marker Q", 0 },
91 	   { "Named Marker R", 0 },
92 	   { "Named Marker S", 0 },
93 	   { "Named Marker T", 0 },
94 	   { "Named Marker U", 0 },
95 	   { "Named Marker V", 0 },
96 	   { "Named Marker W", 0 },
97 	   { "Named Marker X", 0 },
98 	   { "Named Marker Y", 0 },
99 	   { "Named Marker Z", 0 }
100 	};
101 
102 
103 /*
104  * naive nonoptimized case insensitive strstr
105  */
strstr_i(char * hay,char * needle)106 char *strstr_i(char *hay, char *needle)
107 {
108 char *ht, *nt;
109 
110 while (*hay)
111 	{
112 	int offs = 0;
113 	ht = hay; nt = needle;
114 	while(*nt)
115 		{
116 		if(toupper((int)(unsigned char)*(ht+offs)) != toupper((int)(unsigned char)*nt)) break;
117 		offs++;
118 		nt++;
119 		}
120 
121 	if(!*nt) return(hay);
122 	hay++;
123 	}
124 
125 return(*hay ? hay : NULL);
126 }
127 
128 /*
129  * trap timescale overflows
130  */
strace_adjust(TimeType a,TimeType b)131 TimeType strace_adjust(TimeType a, TimeType b)
132 {
133 TimeType res=a+b;
134 
135 if((b>LLDescriptor(0))&&(res<a))
136 	{
137 	return(MAX_HISTENT_TIME);
138 	}
139 
140 return(res);
141 }
142 
143 
144 /*
145  * free the straces...
146  */
count_active_straces(void)147 static int count_active_straces(void)
148 {
149 int s_ctx_iter;
150 int activ = 0;
151 
152 WAVE_STRACE_ITERATOR_FWD(s_ctx_iter)
153         {
154         struct strace_ctx_t *strace_ctx = &GLOBALS->strace_windows[s_ctx_iter];
155 
156 	if(strace_ctx->window_strace_c_10) activ++;
157 	}
158 
159 return(activ);
160 }
161 
162 
163 /*
164  * free the straces...
165  */
free_straces(void)166 static void free_straces(void)
167 {
168 struct strace *s, *skill;
169 int i;
170 struct strace_defer_free *sd, *sd2;
171 
172 s=GLOBALS->strace_ctx->straces;
173 
174 while(s)
175 	{
176 	for(i=0;i<WAVE_STYPE_COUNT;i++)
177 		{
178 		if(s->back[i]) free_2(s->back[i]);
179 		}
180 	if(s->string) free_2(s->string);
181 	skill=s;
182 	s=s->next;
183 	free_2(skill);
184 	}
185 
186 GLOBALS->strace_ctx->straces=NULL;
187 
188 
189 if(count_active_straces() <= 1) /* only free up traces if there is only one pattern search active.  we could splice across multiple strace_ctx but it's not worth the effort here */
190 	{
191 	sd = GLOBALS->strace_ctx->strace_defer_free_head;
192 
193 	while(sd)
194 		{
195 		FreeTrace(sd->defer);
196 		sd2 = sd->next;
197 		free_2(sd);
198 		sd = sd2;
199 		}
200 
201 	GLOBALS->strace_ctx->strace_defer_free_head = NULL; /* moved inside if() so it frees eventually and doesn't stay around until context cleanup */
202 	}
203 }
204 
205 /*
206  * button/menu/entry activations..
207  */
logical_clicked(GtkWidget * widget,gpointer which)208 static void logical_clicked(GtkWidget *widget, gpointer which)
209 {
210 int i;
211 char *which_char;
212 
213 GET_WV_STRACE_CURWIN(widget);
214 
215 for(i=0;i<6;i++) GLOBALS->strace_ctx->logical_mutex[i]=0;
216 which_char=(char *)which;
217 *which_char=1;			/* mark our choice */
218 }
219 
stype_clicked(GtkWidget * widget,gpointer back)220 static void stype_clicked(GtkWidget *widget, gpointer back)
221 {
222 struct strace_back *b;
223 struct strace *s;
224 
225 GET_WV_STRACE_CURWIN(widget);
226 
227 b=(struct strace_back *)back;
228 s=b->parent;
229 
230 s->value=b->which;
231 
232 DEBUG(printf("Trace %s Search Type: %s\n", s->trace->name, stype[(int)s->value]));
233 }
234 
start_clicked(GtkWidget * widget,gpointer which)235 static void start_clicked(GtkWidget *widget, gpointer which)
236 {
237 GET_WV_STRACE_CURWIN(widget);
238 
239 GLOBALS->strace_ctx->mark_idx_start=((struct item_mark_string*)which)->idx;
240 if (GLOBALS->strace_ctx->mark_idx_start<0 || GLOBALS->strace_ctx->mark_idx_start>=(int)(sizeof(item_mark_start_strings)/sizeof(struct item_mark_string)))
241 	{
242 	fprintf(stderr, "Internal error: GLOBALS->mark_idx_start out of range %d\n", GLOBALS->strace_ctx->mark_idx_start);
243 	exit(255);
244 	}
245 DEBUG(printf("start: %s\n", ((struct item_mark_string*)which)->str));
246 }
247 
end_clicked(GtkWidget * widget,gpointer which)248 static void end_clicked(GtkWidget *widget, gpointer which)
249 {
250 GET_WV_STRACE_CURWIN(widget);
251 
252 GLOBALS->strace_ctx->mark_idx_end=((struct item_mark_string*)which)->idx;
253 if (GLOBALS->strace_ctx->mark_idx_end<0 || GLOBALS->strace_ctx->mark_idx_end>=(int)(sizeof(item_mark_end_strings)/sizeof(struct item_mark_string)))
254 	{
255 	fprintf(stderr, "Internal error: GLOBALS->mark_idx_end out of range %d\n",GLOBALS->strace_ctx->mark_idx_end);
256 	exit(255);
257 	}
258 DEBUG(printf("end: %s\n", ((struct item_mark_string*)which)->str));
259 }
260 
enter_callback(GtkWidget * widget,gpointer strace_tmp)261 static void enter_callback(GtkWidget *widget, gpointer strace_tmp)
262 {
263 G_CONST_RETURN gchar *entry_text;
264 struct strace *s;
265 int i, len;
266 
267 GET_WV_STRACE_CURWIN(widget);
268 
269 s=(struct strace *)strace_tmp;
270 if(s->string) { free_2(s->string); s->string=NULL; }
271 
272 entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
273 entry_text = entry_text ? entry_text : "";
274 DEBUG(printf("Trace %s Entry contents: %s\n", s->trace->name, entry_text));
275 
276 if(!(len=strlen(entry_text))) return;
277 
278 gtk_entry_select_region (GTK_ENTRY (widget),
279                              0, GTK_ENTRY(widget)->text_length);
280 
281 strcpy((s->string=(char *)malloc_2(len+1)),entry_text);
282 for(i=0;i<len;i++)
283 	{
284 	char ch;
285 	ch=s->string[i];
286 	if((ch>='a')&&(ch<='z')) s->string[i]=ch-('a'-'A');
287 	}
288 }
289 
forwards_callback(GtkWidget * widget,GtkWidget * nothing)290 static void forwards_callback(GtkWidget *widget, GtkWidget *nothing)
291 {
292 (void)nothing;
293 
294 GET_WV_STRACE_CURWIN(widget);
295 
296 /* no cleanup necessary, but do real search */
297 DEBUG(printf("Searching Forward..\n"));
298 strace_search(STRACE_FORWARD);
299 }
300 
backwards_callback(GtkWidget * widget,GtkWidget * nothing)301 static void backwards_callback(GtkWidget *widget, GtkWidget *nothing)
302 {
303 (void)nothing;
304 
305 GET_WV_STRACE_CURWIN(widget);
306 
307 /* no cleanup necessary, but do real search */
308 DEBUG(printf("Searching Backward..\n"));
309 strace_search(STRACE_BACKWARD);
310 }
311 
mark_callback(GtkWidget * widget,GtkWidget * nothing)312 static void mark_callback(GtkWidget *widget, GtkWidget *nothing)
313 {
314 (void)nothing;
315 
316 GET_WV_STRACE_CURWIN(widget);
317 
318 DEBUG(printf("Marking..\n"));
319 if(GLOBALS->strace_ctx->shadow_straces)
320 	{
321 	delete_strace_context();
322 	}
323 
324 strace_maketimetrace(1);
325 cache_actual_pattern_mark_traces();
326 
327 MaxSignalLength();
328 signalarea_configure_event(GLOBALS->signalarea, NULL);
329 wavearea_configure_event(GLOBALS->wavearea, NULL);
330 }
331 
clear_callback(GtkWidget * widget,GtkWidget * nothing)332 static void clear_callback(GtkWidget *widget, GtkWidget *nothing)
333 {
334 (void)nothing;
335 
336 GET_WV_STRACE_CURWIN(widget);
337 
338 DEBUG(printf("Clearing..\n"));
339 if(GLOBALS->strace_ctx->shadow_straces)
340 	{
341 	delete_strace_context();
342 	}
343 strace_maketimetrace(0);
344 
345 MaxSignalLength();
346 signalarea_configure_event(GLOBALS->signalarea, NULL);
347 wavearea_configure_event(GLOBALS->wavearea, NULL);
348 }
349 
destroy_callback(GtkWidget * widget,GtkWidget * nothing)350 static void destroy_callback(GtkWidget *widget, GtkWidget *nothing)
351 {
352 (void)nothing;
353 
354   GET_WV_STRACE_CURWIN(widget);
355 
356   free_straces();
357   GLOBALS->strace_ctx->ptr_mark_count_label_strace_c_1=NULL;
358   gtk_widget_destroy(GLOBALS->strace_ctx->window_strace_c_10);
359   GLOBALS->strace_ctx->window_strace_c_10 = NULL;
360 }
361 
362 /* update mark count label on pattern search dialog */
363 
update_mark_count_label(void)364 static void update_mark_count_label(void)
365 {
366 if(GLOBALS->strace_ctx->ptr_mark_count_label_strace_c_1)
367     {
368     char mark_count_buf[64];
369     sprintf (mark_count_buf, "Mark Count: %d", GLOBALS->strace_ctx->timearray_size);
370     gtk_label_set_text (GTK_LABEL(GLOBALS->strace_ctx->ptr_mark_count_label_strace_c_1), mark_count_buf);
371     }
372 }
373 
tracesearchbox(const char * title,GtkSignalFunc func,gpointer data)374 void tracesearchbox(const char *title, GtkSignalFunc func, gpointer data)
375 {
376     GtkWidget *menu, *menuitem, *optionmenu;
377     GSList *group;
378     GtkWidget *entry;
379     GtkWidget *vbox, *hbox, *small_hbox, *vbox_g, *label;
380     GtkWidget *button1, *button1a, *button1b, *button1c, *button2, *scrolled_win, *frame, *separator;
381     Trptr t;
382     int i;
383     int numtraces;
384 
385     GLOBALS->strace_current_window = (int)(intptr_t)data; /* arg for which search box going in */
386     GLOBALS->strace_ctx = &GLOBALS->strace_windows[GLOBALS->strace_current_window];
387 
388     /* fix problem where ungrab doesn't occur if button pressed + simultaneous accelerator key occurs */
389     if(GLOBALS->in_button_press_wavewindow_c_1) { gdk_pointer_ungrab(GDK_CURRENT_TIME); }
390 
391     if(GLOBALS->strace_ctx->straces)
392 	{
393 	gdk_window_raise(GLOBALS->strace_ctx->window_strace_c_10->window);
394 	return; /* is already active */
395 	}
396 
397     GLOBALS->strace_ctx->cleanup_strace_c_7=func;
398     numtraces=0;
399 
400     /* create a new window */
401     GLOBALS->strace_ctx->window_strace_c_10 = gtk_window_new(GLOBALS->disable_window_manager ? GTK_WINDOW_POPUP : GTK_WINDOW_TOPLEVEL);
402 
403     GLOBALS->strace_windows[GLOBALS->strace_current_window].window_strace_c_10 = gtk_window_new(GLOBALS->disable_window_manager ? GTK_WINDOW_POPUP : GTK_WINDOW_TOPLEVEL);
404     install_focus_cb(GLOBALS->strace_windows[GLOBALS->strace_current_window].window_strace_c_10,
405 		((char *)&GLOBALS->strace_windows[GLOBALS->strace_current_window].window_strace_c_10) - ((char *)GLOBALS));
406 
407     gtk_window_set_title(GTK_WINDOW (GLOBALS->strace_ctx->window_strace_c_10), title);
408     gtk_widget_set_usize( GTK_WIDGET (GLOBALS->strace_ctx->window_strace_c_10), 420, -1);
409     gtkwave_signal_connect(GTK_OBJECT (GLOBALS->strace_ctx->window_strace_c_10), "delete_event",(GtkSignalFunc) destroy_callback, NULL);
410     WV_STRACE_CURWIN(GLOBALS->strace_ctx->window_strace_c_10);
411 
412     vbox = gtk_vbox_new (FALSE, 0);
413     gtk_container_add (GTK_CONTAINER (GLOBALS->strace_ctx->window_strace_c_10), vbox);
414     gtk_widget_show (vbox);
415 
416     vbox_g = gtk_vbox_new (FALSE, 0);
417     gtk_widget_show (vbox_g);
418 
419     frame = gtk_frame_new (NULL);
420     gtk_container_border_width (GTK_CONTAINER (frame), 3);
421     gtk_widget_show(frame);
422 
423     small_hbox = gtk_hbox_new (TRUE, 0);
424     gtk_widget_show (small_hbox);
425 
426     label=gtk_label_new("Logical Operation");
427     gtk_widget_show (label);
428     gtk_box_pack_start (GTK_BOX (small_hbox), label, TRUE, FALSE, 0);
429 
430 
431     menu = gtk_menu_new ();
432     group=NULL;
433 
434     for(i=0;i<6;i++)
435 	{
436     	menuitem = gtk_radio_menu_item_new_with_label (group, logical[i]);
437     	group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem));
438     	gtk_menu_append (GTK_MENU (menu), menuitem);
439     	gtk_widget_show (menuitem);
440         gtkwave_signal_connect(GTK_OBJECT (menuitem), "activate", GTK_SIGNAL_FUNC(logical_clicked), &GLOBALS->strace_ctx->logical_mutex[i]);
441 	WV_STRACE_CURWIN(menuitem);
442 	GLOBALS->strace_ctx->logical_mutex[i]=0;
443 	}
444 
445 	GLOBALS->strace_ctx->logical_mutex[0]=1;	/* "and" */
446 
447 	optionmenu = gtk_option_menu_new ();
448 	gtk_option_menu_set_menu (GTK_OPTION_MENU (optionmenu), menu);
449 	gtk_box_pack_start (GTK_BOX (small_hbox), optionmenu, TRUE, FALSE, 0);
450 	gtk_widget_show (optionmenu);
451 
452 	gtk_box_pack_start (GTK_BOX (vbox), small_hbox, FALSE, FALSE, 0);
453 
454     scrolled_win = gtk_scrolled_window_new (NULL, NULL);
455     gtk_widget_set_usize( GTK_WIDGET (scrolled_win), -1, 300);
456     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
457                                       GTK_POLICY_AUTOMATIC,
458                                       GTK_POLICY_AUTOMATIC);
459     gtk_widget_show(scrolled_win);
460     gtk_container_add (GTK_CONTAINER (frame), scrolled_win);
461     gtk_container_add (GTK_CONTAINER (vbox), frame);
462 
463     for(t=GLOBALS->traces.first;t;t=t->t_next)
464     {
465     struct strace *s;
466 
467     if ((t->flags&(TR_BLANK|TR_ANALOG_BLANK_STRETCH))||(!(t->flags&TR_HIGHLIGHT))||(!(t->name))) continue;
468 
469     numtraces++;
470     if(numtraces==500)
471 	{
472 	status_text("Limiting waveform display search to 500 traces.\n");
473 	break;
474 	}
475 
476     s=(struct strace *)calloc_2(1,sizeof(struct strace));
477     s->next=GLOBALS->strace_ctx->straces;
478     GLOBALS->strace_ctx->straces=s;
479     s->trace=t;
480 
481     if(t!=GLOBALS->traces.first)
482 	{
483     	separator = gtk_hseparator_new ();
484     	gtk_widget_show (separator);
485     	gtk_box_pack_start (GTK_BOX (vbox_g), separator, FALSE, FALSE, 0);
486 	}
487 
488     small_hbox = gtk_hbox_new (TRUE, 0);
489     gtk_widget_show (small_hbox);
490 
491     label=gtk_label_new(t->name);
492     gtk_widget_show (label);
493     gtk_box_pack_start (GTK_BOX (vbox_g), label, FALSE, FALSE, 0);
494 
495     menu = gtk_menu_new ();
496     group=NULL;
497 
498     for(i=0;i<WAVE_STYPE_COUNT;i++)
499 	{
500 	struct strace_back *b;
501 
502 	b=(struct strace_back *)calloc_2(1,sizeof(struct strace_back));
503 	b->parent=s;
504 	b->which=i;
505 	s->back[i]=b;
506     	menuitem = gtk_radio_menu_item_new_with_label (group, stype[i]);
507     	group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem));
508     	gtk_menu_append (GTK_MENU (menu), menuitem);
509     	gtk_widget_show (menuitem);
510         gtkwave_signal_connect(GTK_OBJECT (menuitem), "activate", GTK_SIGNAL_FUNC(stype_clicked), b);
511 	WV_STRACE_CURWIN(menuitem);
512 	}
513 
514 	optionmenu = gtk_option_menu_new ();
515 	gtk_option_menu_set_menu (GTK_OPTION_MENU (optionmenu), menu);
516 	gtk_box_pack_start (GTK_BOX (small_hbox), optionmenu, TRUE, FALSE, 0);
517 	gtk_widget_show (optionmenu);
518 
519     entry = gtk_entry_new_with_max_length (257); /* %+256ch */
520     gtkwave_signal_connect(GTK_OBJECT(entry), "activate", GTK_SIGNAL_FUNC(enter_callback), s);
521     gtkwave_signal_connect(GTK_OBJECT(entry), "changed", GTK_SIGNAL_FUNC(enter_callback), s);
522     WV_STRACE_CURWIN(entry);
523 
524     gtk_box_pack_start (GTK_BOX (small_hbox), entry, TRUE, FALSE, 0);
525     gtk_widget_show (entry);
526     gtk_box_pack_start (GTK_BOX (vbox_g), small_hbox, FALSE, FALSE, 0);
527     }
528 
529     gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_win), vbox_g);
530 
531     do		/* add GUI elements for displaying mark count and mark count start/end */
532 	{
533 	unsigned int idx;
534 	GtkWidget *ptr_mark_start_label, *ptr_mark_end_label;
535 	GtkWidget *mark_count_hbox_start,  *mark_count_hbox_end;
536 	GtkWidget *count_vbox_left, *count_vbox_right, *count_vbox, *count_hbox;
537 	GtkWidget *ptr_mark_count_start, *ptr_mark_count_end;
538 
539 	count_hbox=gtk_hbox_new (TRUE, 0);
540 	gtk_widget_show (count_hbox);
541 	gtk_box_pack_start (GTK_BOX(vbox),count_hbox,FALSE,FALSE,0);
542 
543 		/* add a vertical box to display the mark count GUI elements */
544 	count_vbox_left=gtk_vbox_new (TRUE, 0);
545 	gtk_widget_show (count_vbox_left);
546 	gtk_box_pack_start (GTK_BOX(count_hbox),count_vbox_left,FALSE,FALSE,0);
547 	count_vbox=gtk_vbox_new (TRUE, 0);
548 	gtk_widget_show (count_vbox);
549 	gtk_box_pack_start (GTK_BOX(count_hbox),count_vbox,FALSE,FALSE,0);
550 	count_vbox_right=gtk_vbox_new (TRUE, 0);
551 	gtk_widget_show (count_vbox_right);
552 	gtk_box_pack_start (GTK_BOX(count_hbox),count_vbox_right,FALSE,FALSE,0);
553 
554 		/* add mark start GUI element */
555 	mark_count_hbox_start=gtk_hbox_new (TRUE, 0);
556 	gtk_widget_show (mark_count_hbox_start);
557 	gtk_box_pack_start (GTK_BOX(count_vbox),mark_count_hbox_start,FALSE,FALSE,0);
558 	ptr_mark_start_label=gtk_label_new ("Marking Begins at:");
559 	gtk_widget_show (ptr_mark_start_label);
560 	gtk_box_pack_start (GTK_BOX (mark_count_hbox_start),ptr_mark_start_label,TRUE,FALSE,0);
561 	ptr_mark_count_start = gtk_menu_new ();
562 	group=NULL;
563 	for(idx=0; idx<sizeof(item_mark_start_strings)/sizeof(struct item_mark_string); ++idx)
564 		{
565 		item_mark_start_strings[idx].idx=idx;
566     		menuitem = gtk_radio_menu_item_new_with_label (group, item_mark_start_strings[idx].str);
567     		group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem));
568     		gtk_menu_append (GTK_MENU (ptr_mark_count_start), menuitem);
569     		gtk_widget_show (menuitem);
570         	gtkwave_signal_connect(GTK_OBJECT (menuitem), "activate", GTK_SIGNAL_FUNC(start_clicked), &item_mark_start_strings[idx]);
571 		WV_STRACE_CURWIN(menuitem);
572 		}
573 	optionmenu = gtk_option_menu_new ();
574 	gtk_option_menu_set_menu (GTK_OPTION_MENU (optionmenu), ptr_mark_count_start);
575 	gtk_box_pack_start (GTK_BOX (mark_count_hbox_start), optionmenu, TRUE, FALSE, 0);
576 	gtk_widget_show (optionmenu);
577 	gtk_option_menu_set_history (GTK_OPTION_MENU (optionmenu), GLOBALS->strace_ctx->mark_idx_start);
578 
579 		/* add mark end GUI element */
580 	mark_count_hbox_end=gtk_hbox_new (TRUE, 0);
581 	gtk_widget_show (mark_count_hbox_end);
582 	gtk_box_pack_start (GTK_BOX(count_vbox),mark_count_hbox_end,FALSE,FALSE,0);
583 	ptr_mark_end_label=gtk_label_new ("Marking Stops at:");
584 	gtk_widget_show (ptr_mark_end_label);
585 	gtk_box_pack_start (GTK_BOX (mark_count_hbox_end),ptr_mark_end_label,TRUE,FALSE,0);
586 	ptr_mark_count_end = gtk_menu_new ();
587 	group=NULL;
588 	for(idx=0; idx<sizeof(item_mark_end_strings)/sizeof(struct item_mark_string); ++idx)
589 		{
590 		item_mark_end_strings[idx].idx=idx;
591     		menuitem = gtk_radio_menu_item_new_with_label (group, item_mark_end_strings[idx].str);
592     		group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem));
593     		gtk_menu_append (GTK_MENU (ptr_mark_count_end), menuitem);
594     		gtk_widget_show (menuitem);
595         	gtkwave_signal_connect(GTK_OBJECT (menuitem), "activate", GTK_SIGNAL_FUNC(end_clicked), &item_mark_end_strings[idx]);
596 		WV_STRACE_CURWIN(menuitem);
597 		}
598 	optionmenu = gtk_option_menu_new ();
599 	gtk_option_menu_set_menu (GTK_OPTION_MENU (optionmenu), ptr_mark_count_end);
600 	gtk_box_pack_start (GTK_BOX (mark_count_hbox_end), optionmenu, TRUE, FALSE, 0);
601 	gtk_widget_show (optionmenu);
602 	gtk_option_menu_set_history (GTK_OPTION_MENU (optionmenu), GLOBALS->strace_ctx->mark_idx_end);
603 
604 		/* add mark count GUI element */
605 	GLOBALS->strace_ctx->ptr_mark_count_label_strace_c_1=gtk_label_new ("");
606 	gtk_widget_show (GLOBALS->strace_ctx->ptr_mark_count_label_strace_c_1);
607 	gtk_box_pack_start (GTK_BOX (count_vbox),GLOBALS->strace_ctx->ptr_mark_count_label_strace_c_1,TRUE,FALSE,0);
608 	update_mark_count_label ();
609 	} while (0);
610 
611     hbox = gtk_hbox_new (FALSE, 1);
612     gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
613     gtk_widget_show (hbox);
614 
615     button1 = gtk_button_new_with_label ("Fwd");
616     gtk_widget_set_usize(button1, 75, -1);
617     gtkwave_signal_connect(GTK_OBJECT (button1), "clicked", GTK_SIGNAL_FUNC(forwards_callback), NULL);
618     WV_STRACE_CURWIN(button1);
619     gtk_widget_show (button1);
620     gtk_container_add (GTK_CONTAINER (hbox), button1);
621     GTK_WIDGET_SET_FLAGS (button1, GTK_CAN_DEFAULT);
622     gtkwave_signal_connect_object (GTK_OBJECT (button1), "realize", (GtkSignalFunc) gtk_widget_grab_default, GTK_OBJECT (button1));
623 
624 
625     button1a = gtk_button_new_with_label ("Bkwd");
626     gtk_widget_set_usize(button1a, 75, -1);
627     gtkwave_signal_connect(GTK_OBJECT (button1a), "clicked", GTK_SIGNAL_FUNC(backwards_callback), NULL);
628     WV_STRACE_CURWIN(button1a);
629     gtk_widget_show (button1a);
630     gtk_container_add (GTK_CONTAINER (hbox), button1a);
631     GTK_WIDGET_SET_FLAGS (button1a, GTK_CAN_DEFAULT);
632 
633     button1b = gtk_button_new_with_label ("Mark");
634     gtk_widget_set_usize(button1b, 75, -1);
635     gtkwave_signal_connect(GTK_OBJECT (button1b), "clicked", GTK_SIGNAL_FUNC(mark_callback), NULL);
636     WV_STRACE_CURWIN(button1b);
637     gtk_widget_show (button1b);
638     gtk_container_add (GTK_CONTAINER (hbox), button1b);
639     GTK_WIDGET_SET_FLAGS (button1b, GTK_CAN_DEFAULT);
640 
641     button1c = gtk_button_new_with_label ("Clear");
642     gtk_widget_set_usize(button1c, 75, -1);
643     gtkwave_signal_connect(GTK_OBJECT (button1c), "clicked", GTK_SIGNAL_FUNC(clear_callback), NULL);
644     WV_STRACE_CURWIN(button1c);
645     gtk_widget_show (button1c);
646     gtk_container_add (GTK_CONTAINER (hbox), button1c);
647     GTK_WIDGET_SET_FLAGS (button1c, GTK_CAN_DEFAULT);
648 
649     button2 = gtk_button_new_with_label ("Exit");
650     gtk_widget_set_usize(button2, 75, -1);
651     gtkwave_signal_connect(GTK_OBJECT (button2), "clicked", GTK_SIGNAL_FUNC(destroy_callback), NULL);
652     WV_STRACE_CURWIN(button2);
653     GTK_WIDGET_SET_FLAGS (button2, GTK_CAN_DEFAULT);
654     gtk_widget_show (button2);
655     gtk_container_add (GTK_CONTAINER (hbox), button2);
656 
657     gtk_widget_show(GLOBALS->strace_ctx->window_strace_c_10);
658 }
659 
660 
661 /*
662  * strace backward or forward..
663  */
strace_search_2(int direction,int is_last_iteration)664 static void strace_search_2(int direction, int is_last_iteration)
665 {
666 struct strace *s;
667 TimeType basetime, maxbase, sttim, fintim;
668 Trptr t;
669 int totaltraces, passcount;
670 int whichpass;
671 TimeType middle=0, width;
672 
673 
674 if(direction==STRACE_BACKWARD) /* backwards */
675 {
676 if(GLOBALS->tims.marker<0)
677 	{
678 	basetime=MAX_HISTENT_TIME;
679 	}
680 	else
681 	{
682 	basetime=GLOBALS->tims.marker;
683 	}
684 }
685 else /* go forwards */
686 {
687 if(GLOBALS->tims.marker<0)
688 	{
689 	basetime=GLOBALS->tims.first;
690 	}
691 	else
692 	{
693 	basetime=GLOBALS->tims.marker;
694 	}
695 }
696 
697 sttim=GLOBALS->tims.first;
698 fintim=GLOBALS->tims.last;
699 
700 for(whichpass=0;;whichpass++)
701 {
702 
703 if(direction==STRACE_BACKWARD) /* backwards */
704 {
705 maxbase=-1;
706 s=GLOBALS->strace_ctx->straces;
707 while(s)
708 	{
709 	t=s->trace;
710 	GLOBALS->shift_timebase=t->shift;
711 	if(!(t->vector))
712 		{
713 		hptr h;
714 		hptr *hp;
715 		UTimeType utt;
716 		TimeType  tt;
717 
718 		/* h= */ bsearch_node(t->n.nd, basetime - t->shift); /* scan-build */
719 		hp=GLOBALS->max_compare_index;
720 		if((hp==&(t->n.nd->harray[1]))||(hp==&(t->n.nd->harray[0]))) return;
721 		if(basetime == ((*hp)->time+GLOBALS->shift_timebase)) hp--;
722 		h=*hp;
723 		s->his.h=h;
724 		utt=strace_adjust(h->time,GLOBALS->shift_timebase); tt=utt;
725 		if(tt > maxbase) maxbase=tt;
726 		}
727 		else
728 		{
729 		vptr v;
730 		vptr *vp;
731 		UTimeType utt;
732 		TimeType  tt;
733 
734 		/* v= */ bsearch_vector(t->n.vec, basetime - t->shift); /* scan-build */
735 		vp=GLOBALS->vmax_compare_index;
736 		if((vp==&(t->n.vec->vectors[1]))||(vp==&(t->n.vec->vectors[0]))) return;
737 		if(basetime == ((*vp)->time+GLOBALS->shift_timebase)) vp--;
738 		v=*vp;
739 		s->his.v=v;
740 		utt=strace_adjust(v->time,GLOBALS->shift_timebase); tt=utt;
741 		if(tt > maxbase) maxbase=tt;
742 		}
743 
744 	s=s->next;
745 	}
746 }
747 else /* go forward */
748 {
749 maxbase=MAX_HISTENT_TIME;
750 s=GLOBALS->strace_ctx->straces;
751 while(s)
752 	{
753 	t=s->trace;
754 	GLOBALS->shift_timebase=t->shift;
755 	if(!(t->vector))
756 		{
757 		hptr h;
758 		UTimeType utt;
759 		TimeType  tt;
760 
761 		h=bsearch_node(t->n.nd, basetime - t->shift);
762 		while(h->next && h->time==h->next->time) h=h->next;
763 		if((whichpass)||(GLOBALS->tims.marker>=0)) h=h->next;
764 		if(!h) return;
765 		s->his.h=h;
766 		utt=strace_adjust(h->time,GLOBALS->shift_timebase); tt=utt;
767 		if(tt < maxbase) maxbase=tt;
768 		}
769 		else
770 		{
771 		vptr v;
772 		UTimeType utt;
773 		TimeType  tt;
774 
775 		v=bsearch_vector(t->n.vec, basetime - t->shift);
776 		while(v->next && v->time==v->next->time) v=v->next;
777 		if((whichpass)||(GLOBALS->tims.marker>=0)) v=v->next;
778 		if(!v) return;
779 		s->his.v=v;
780 		utt=strace_adjust(v->time,GLOBALS->shift_timebase); tt=utt;
781 		if(tt < maxbase) maxbase=tt;
782 		}
783 
784 	s=s->next;
785 	}
786 }
787 
788 s=GLOBALS->strace_ctx->straces;
789 totaltraces=0;	/* increment when not don't care */
790 while(s)
791 	{
792 	char str[2];
793 	t=s->trace;
794 	s->search_result=0;	/* explicitly must set this */
795 	GLOBALS->shift_timebase=t->shift;
796 
797 	if((!t->vector)&&(!(t->n.nd->extvals)))
798 		{
799 		if(strace_adjust(s->his.h->time,GLOBALS->shift_timebase)!=maxbase)
800 			{
801 			s->his.h=bsearch_node(t->n.nd, maxbase - t->shift);
802 			while(s->his.h->next && s->his.h->time==s->his.h->next->time) s->his.h=s->his.h->next;
803 			}
804 		if(t->flags&TR_INVERT)
805                 	{
806                         str[0]=AN_STR_INV[s->his.h->v.h_val];
807                         }
808                         else
809                         {
810                         str[0]=AN_STR[s->his.h->v.h_val];
811                         }
812 		str[1]=0x00;
813 
814 		switch(s->value)
815 			{
816 			case ST_DC:
817 				break;
818 
819 			case ST_HIGH:
820 				totaltraces++;
821 				if((str[0]=='1')||(str[0]=='h')||(str[0]=='H')) s->search_result=1;
822 				break;
823 
824 			case ST_RISE:
825 				if((str[0]=='1')||(str[0]=='h')||(str[0]=='H')) s->search_result=1;
826 				totaltraces++;
827 				break;
828 
829 			case ST_LOW:
830 				totaltraces++;
831 				if((str[0]=='0')||(str[0]=='l')||(str[0]=='L')) s->search_result=1;
832 				break;
833 
834 			case ST_FALL:
835 				totaltraces++;
836 				if((str[0]=='0')||(str[0]=='l')||(str[0]=='L')) s->search_result=1;
837 				break;
838 
839 			case ST_MID:
840 				totaltraces++;
841 				if((str[0]=='z')||(str[0]=='Z'))
842  					s->search_result=1;
843 				break;
844 
845 			case ST_X:
846 				totaltraces++;
847 				if((str[0]=='x')||(str[0]=='X')) s->search_result=1;
848 				break;
849 
850 			case ST_ANY:
851 				totaltraces++;
852 				s->search_result=1;
853 				break;
854 
855 			case ST_STRING:
856 				totaltraces++;
857 				if(s->string)
858 				if(strstr_i(s->string,str)) s->search_result=1;
859 				break;
860 
861 			default:
862 				fprintf(stderr, "Internal error: st_type of %d\n",s->value);
863 				exit(255);
864 			}
865 
866 
867 		}
868 		else
869 		{
870 		char *chval, *chval2;
871 		char ch;
872 
873 		if(t->vector)
874 			{
875 			if(strace_adjust(s->his.v->time,GLOBALS->shift_timebase)!=maxbase)
876 				{
877 				s->his.v=bsearch_vector(t->n.vec, maxbase - t->shift);
878 				while(s->his.v->next && s->his.v->time==s->his.v->next->time) s->his.v=s->his.v->next;
879 				}
880 			chval=convert_ascii(t,s->his.v);
881 			}
882 			else
883 			{
884 			if(strace_adjust(s->his.h->time,GLOBALS->shift_timebase)!=maxbase)
885 				{
886 				s->his.h=bsearch_node(t->n.nd, maxbase - t->shift);
887 				while(s->his.h->next && s->his.h->time==s->his.h->next->time) s->his.h=s->his.h->next;
888 				}
889 			if(s->his.h->flags&HIST_REAL)
890 				{
891 				if(!(s->his.h->flags&HIST_STRING))
892 					{
893 #ifdef WAVE_HAS_H_DOUBLE
894 					chval=convert_ascii_real(t, &s->his.h->v.h_double);
895 #else
896 					chval=convert_ascii_real(t, (double *)s->his.h->v.h_vector);
897 #endif
898 					}
899 					else
900 					{
901 					chval=convert_ascii_string((char *)s->his.h->v.h_vector);
902 					chval2=chval;
903 					while((ch=*chval2))	/* toupper() the string */
904 						{
905 						if((ch>='a')&&(ch<='z')) { *chval2= ch-('a'-'A'); }
906 						chval2++;
907 						}
908 					}
909 				}
910 				else
911 				{
912 				chval=convert_ascii_vec(t,s->his.h->v.h_vector);
913 				}
914 			}
915 
916 		switch(s->value)
917 			{
918 			case ST_DC:
919 				break;
920 
921 			case ST_RISE:
922 			case ST_FALL:
923 				totaltraces++;
924 				break;
925 
926 			case ST_HIGH:
927 				totaltraces++;
928 				if((chval2=chval))
929 				while((ch=*(chval2++)))
930 					{
931 					if(((ch>='1')&&(ch<='9'))||(ch=='h')||(ch=='H')||((ch>='A')&&(ch<='F')))
932 						{
933 						s->search_result=1;
934 						break;
935 						}
936 					}
937 				break;
938 
939 			case ST_LOW:
940 				totaltraces++;
941 				if((chval2=chval))
942 				{
943 				s->search_result=1;
944 				while((ch=*(chval2++)))
945 					{
946 					if((ch!='0')&&(ch!='l')&&(ch!='L'))
947 						{
948 						s->search_result=0;
949 						break;
950 						}
951 					}
952 				}
953 				break;
954 
955 			case ST_MID:
956 				totaltraces++;
957 				if((chval2=chval))
958 				{
959 				s->search_result=1;
960 				while((ch=*(chval2++)))
961 					{
962 					if((ch!='z')&&(ch!='Z'))
963 						{
964 						s->search_result=0;
965 						break;
966 						}
967 					}
968 				}
969 				break;
970 
971 			case ST_X:
972 				totaltraces++;
973 				if((chval2=chval))
974 				{
975 				s->search_result=1;
976 				while((ch=*(chval2++)))
977 					{
978 					if((ch!='x')&&(ch!='w')&&(ch!='X')&&(ch!='W'))
979 						{
980 						s->search_result=0;
981 						break;
982 						}
983 					}
984 				}
985 				break;
986 
987 			case ST_ANY:
988 				totaltraces++;
989 				s->search_result=1;
990 				break;
991 
992 			case ST_STRING:
993 				totaltraces++;
994 				if(s->string)
995 				if(strstr_i(chval, s->string)) s->search_result=1;
996 				break;
997 
998 			default:
999 				fprintf(stderr, "Internal error: st_type of %d\n",s->value);
1000 				exit(255);
1001 			}
1002 
1003 		free_2(chval);
1004 		}
1005 	s=s->next;
1006 	}
1007 
1008 if((maxbase<sttim)||(maxbase>fintim)) return;
1009 
1010 DEBUG(printf("Maxbase: "TTFormat", total traces: %d\n",maxbase, totaltraces));
1011 s=GLOBALS->strace_ctx->straces;
1012 passcount=0;
1013 while(s)
1014 	{
1015 	DEBUG(printf("\tPass: %d, Name: %s\n",s->search_result, s->trace->name));
1016 	if(s->search_result) passcount++;
1017 	s=s->next;
1018 	}
1019 
1020 if(totaltraces)
1021 	{
1022 	if(GLOBALS->strace_ctx->logical_mutex[0])	/* and */
1023 		{
1024 		if(totaltraces==passcount) break;
1025 		}
1026 	else
1027 	if(GLOBALS->strace_ctx->logical_mutex[1])	/* or */
1028 		{
1029 		if(passcount) break;
1030 		}
1031 	else
1032 	if(GLOBALS->strace_ctx->logical_mutex[2])	/* xor */
1033 		{
1034 		if(passcount&1) break;
1035 		}
1036 	else
1037 	if(GLOBALS->strace_ctx->logical_mutex[3])	/* nand */
1038 		{
1039 		if(totaltraces!=passcount) break;
1040 		}
1041 	else
1042 	if(GLOBALS->strace_ctx->logical_mutex[4])	/* nor */
1043 		{
1044 		if(!passcount) break;
1045 		}
1046 	else
1047 	if(GLOBALS->strace_ctx->logical_mutex[5])	/* xnor */
1048 		{
1049 		if(!(passcount&1)) break;
1050 		}
1051 	}
1052 
1053 basetime=maxbase;
1054 }
1055 
1056 GLOBALS->tims.marker=maxbase;
1057 if(is_last_iteration)
1058 	{
1059 	update_markertime(GLOBALS->tims.marker);
1060 
1061 	width=(TimeType)(((gdouble)GLOBALS->wavewidth)*GLOBALS->nspx);
1062 	if((GLOBALS->tims.marker<GLOBALS->tims.start)||(GLOBALS->tims.marker>=GLOBALS->tims.start+width))
1063 		{
1064 		if((GLOBALS->tims.marker<0)||(GLOBALS->tims.marker<GLOBALS->tims.first)||(GLOBALS->tims.marker>GLOBALS->tims.last))
1065 		                {
1066 		                if(GLOBALS->tims.end>GLOBALS->tims.last) GLOBALS->tims.end=GLOBALS->tims.last;
1067 		                middle=(GLOBALS->tims.start/2)+(GLOBALS->tims.end/2);
1068 		                if((GLOBALS->tims.start&1)&&(GLOBALS->tims.end&1)) middle++;
1069 		                }
1070 		                else
1071 		                {
1072 		                middle=GLOBALS->tims.marker;
1073 		                }
1074 
1075 		GLOBALS->tims.start=time_trunc(middle-(width/2));
1076 		if(GLOBALS->tims.start+width>GLOBALS->tims.last) GLOBALS->tims.start=GLOBALS->tims.last-width;
1077 		if(GLOBALS->tims.start<GLOBALS->tims.first) GLOBALS->tims.start=GLOBALS->tims.first;
1078 		GTK_ADJUSTMENT(GLOBALS->wave_hslider)->value=GLOBALS->tims.timecache=GLOBALS->tims.start;
1079 		}
1080 
1081 	MaxSignalLength();
1082 	signalarea_configure_event(GLOBALS->signalarea, NULL);
1083 	wavearea_configure_event(GLOBALS->wavearea, NULL);
1084 	}
1085 }
1086 
1087 
strace_search(int direction)1088 void strace_search(int direction)
1089 {
1090 int i;
1091 int i_high_cnt = ((GLOBALS->strace_repeat_count > 0) ? GLOBALS->strace_repeat_count : 1) - 1;
1092 
1093 for(i=0;i<=i_high_cnt;i++)
1094         {
1095         strace_search_2(direction, (i == i_high_cnt));
1096         }
1097 }
1098 
1099 
1100 /*********************************************/
1101 
1102 /*
1103  * strace forward to make the timetrace
1104  */
strace_timetrace(TimeType basetime,int notfirst)1105 TimeType strace_timetrace(TimeType basetime, int notfirst)
1106 {
1107 struct strace *s;
1108 TimeType maxbase, fintim;
1109 Trptr t;
1110 int totaltraces, passcount;
1111 int whichpass;
1112 
1113 fintim=GLOBALS->tims.last;
1114 
1115 for(whichpass=0;;whichpass++)
1116 {
1117 maxbase=MAX_HISTENT_TIME;
1118 s=GLOBALS->strace_ctx->straces;
1119 while(s)
1120 	{
1121 	t=s->trace;
1122 	GLOBALS->shift_timebase=t->shift;
1123 	if(!(t->vector))
1124 		{
1125 		hptr h;
1126 		UTimeType utt;
1127 		TimeType  tt;
1128 
1129 		h=bsearch_node(t->n.nd, basetime - t->shift);
1130 		s->his.h=h;
1131 		while(h->time==h->next->time) h=h->next;
1132 		if((whichpass)||(notfirst)) h=h->next;
1133 		if(!h) return(MAX_HISTENT_TIME);
1134 		utt=strace_adjust(h->time,GLOBALS->shift_timebase); tt=utt;
1135 		if(tt < maxbase) maxbase=tt;
1136 		}
1137 		else
1138 		{
1139 		vptr v;
1140 		UTimeType utt;
1141 		TimeType  tt;
1142 
1143 		v=bsearch_vector(t->n.vec, basetime - t->shift);
1144 		if((whichpass)||(notfirst)) v=v->next;
1145 		if(!v) return(MAX_HISTENT_TIME);
1146 		s->his.v=v;
1147 		utt=strace_adjust(v->time,GLOBALS->shift_timebase); tt=utt;
1148 		if(tt < maxbase) maxbase=tt;
1149 		}
1150 
1151 	s=s->next;
1152 	}
1153 
1154 s=GLOBALS->strace_ctx->straces;
1155 totaltraces=0;	/* increment when not don't care */
1156 while(s)
1157 	{
1158 	char str[2];
1159 	t=s->trace;
1160 	s->search_result=0;	/* explicitly must set this */
1161 	GLOBALS->shift_timebase=t->shift;
1162 
1163 	if((!t->vector)&&(!(t->n.nd->extvals)))
1164 		{
1165 		if(strace_adjust(s->his.h->time,GLOBALS->shift_timebase)!=maxbase)
1166 			{
1167 			s->his.h=bsearch_node(t->n.nd, maxbase - t->shift);
1168 			while(s->his.h->next && s->his.h->time==s->his.h->next->time) s->his.h=s->his.h->next;
1169 			}
1170 		if(t->flags&TR_INVERT)
1171                 	{
1172                         str[0]=AN_STR_INV[s->his.h->v.h_val];
1173                         }
1174                         else
1175                         {
1176                         str[0]=AN_STR[s->his.h->v.h_val];
1177                         }
1178 		str[1]=0x00;
1179 
1180 		switch(s->value)
1181 			{
1182 			case ST_DC:
1183 				break;
1184 
1185 			case ST_HIGH:
1186 				totaltraces++;
1187 				if((str[0]=='1')||(str[0]=='h')||(str[0]=='H')) s->search_result=1;
1188 				break;
1189 
1190 			case ST_RISE:
1191 				totaltraces++;
1192 				if(((str[0]=='1')||(str[0]=='h')||(str[0]=='H'))&&(strace_adjust(s->his.h->time,GLOBALS->shift_timebase)==maxbase))
1193 					s->search_result=1;
1194 				break;
1195 
1196 			case ST_LOW:
1197 				totaltraces++;
1198 				if((str[0]=='0')||(str[0]=='l')||(str[0]=='L')) s->search_result=1;
1199 				break;
1200 
1201 			case ST_FALL:
1202 				totaltraces++;
1203 				if(((str[0]=='0')||(str[0]=='l')||(str[0]=='L'))&&(strace_adjust(s->his.h->time,GLOBALS->shift_timebase)==maxbase))
1204  					s->search_result=1;
1205 				break;
1206 
1207 			case ST_MID:
1208 				totaltraces++;
1209 				if((str[0]=='z')||(str[0]=='Z'))
1210  					s->search_result=1;
1211 				break;
1212 
1213 			case ST_X:
1214 				totaltraces++;
1215 				if((str[0]=='x')||(str[0]=='X')) s->search_result=1;
1216 				break;
1217 
1218 			case ST_ANY:
1219 				totaltraces++;
1220 				if(strace_adjust(s->his.h->time,GLOBALS->shift_timebase)==maxbase)s->search_result=1;
1221 				break;
1222 
1223 			case ST_STRING:
1224 				totaltraces++;
1225 				if(s->string)
1226 				if(strstr_i(s->string,str)) s->search_result=1;
1227 				break;
1228 
1229 			default:
1230 				fprintf(stderr, "Internal error: st_type of %d\n",s->value);
1231 				exit(255);
1232 			}
1233 
1234 
1235 		}
1236 		else
1237 		{
1238 		char *chval, *chval2;
1239 		char ch;
1240 
1241 		if(t->vector)
1242 			{
1243 			if(strace_adjust(s->his.v->time,GLOBALS->shift_timebase)!=maxbase)
1244 				{
1245 				s->his.v=bsearch_vector(t->n.vec, maxbase - t->shift);
1246 				while(s->his.v->next && s->his.v->time==s->his.v->next->time) s->his.v=s->his.v->next;
1247 				}
1248 			chval=convert_ascii(t,s->his.v);
1249 			}
1250 			else
1251 			{
1252 			if(strace_adjust(s->his.h->time,GLOBALS->shift_timebase)!=maxbase)
1253 				{
1254 				s->his.h=bsearch_node(t->n.nd, maxbase - t->shift);
1255 				while(s->his.h->next && s->his.h->time==s->his.h->next->time) s->his.h=s->his.h->next;
1256 				}
1257 			if(s->his.h->flags&HIST_REAL)
1258 				{
1259 				if(!(s->his.h->flags&HIST_STRING))
1260 					{
1261 #ifdef WAVE_HAS_H_DOUBLE
1262 					chval=convert_ascii_real(t, &s->his.h->v.h_double);
1263 #else
1264 					chval=convert_ascii_real(t, (double *)s->his.h->v.h_vector);
1265 #endif
1266 					}
1267 					else
1268 					{
1269 					chval=convert_ascii_string((char *)s->his.h->v.h_vector);
1270 					chval2=chval;
1271 					while((ch=*chval2))	/* toupper() the string */
1272 						{
1273 						if((ch>='a')&&(ch<='z')) { *chval2= ch-('a'-'A'); }
1274 						chval2++;
1275 						}
1276 					}
1277 				}
1278 				else
1279 				{
1280 				chval=convert_ascii_vec(t,s->his.h->v.h_vector);
1281 				}
1282 			}
1283 
1284 		switch(s->value)
1285 			{
1286 			case ST_DC:
1287 				break;
1288 
1289 			case ST_RISE:
1290 			case ST_FALL:
1291 				totaltraces++;
1292 				break;
1293 
1294 			case ST_HIGH:
1295 				totaltraces++;
1296 				if((chval2=chval))
1297 				while((ch=*(chval2++)))
1298 					{
1299 					if(((ch>='1')&&(ch<='9'))||(ch=='h')||(ch=='H')||((ch>='A')&&(ch<='F')))
1300 						{
1301 						s->search_result=1;
1302 						break;
1303 						}
1304 					}
1305 				break;
1306 
1307 			case ST_LOW:
1308 				totaltraces++;
1309 				if((chval2=chval))
1310 				{
1311 				s->search_result=1;
1312 				while((ch=*(chval2++)))
1313 					{
1314 					if((ch!='0')&&(ch!='l')&&(ch!='L'))
1315 						{
1316 						s->search_result=0;
1317 						break;
1318 						}
1319 					}
1320 				}
1321 				break;
1322 
1323 			case ST_MID:
1324 				totaltraces++;
1325 				if((chval2=chval))
1326 				{
1327 				s->search_result=1;
1328 				while((ch=*(chval2++)))
1329 					{
1330 					if((ch!='z')&&(ch!='Z'))
1331 						{
1332 						s->search_result=0;
1333 						break;
1334 						}
1335 					}
1336 				}
1337 				break;
1338 
1339 			case ST_X:
1340 				totaltraces++;
1341 				if((chval2=chval))
1342 				{
1343 				s->search_result=1;
1344 				while((ch=*(chval2++)))
1345 					{
1346 					if((ch!='x')&&(ch!='w')&&(ch!='X')&&(ch!='W'))
1347 						{
1348 						s->search_result=0;
1349 						break;
1350 						}
1351 					}
1352 				}
1353 				break;
1354 
1355 			case ST_ANY:
1356 				totaltraces++;
1357 				if(strace_adjust(s->his.v->time,GLOBALS->shift_timebase)==maxbase)
1358 					s->search_result=1;
1359 				break;
1360 
1361 			case ST_STRING:
1362 				totaltraces++;
1363 				if(s->string)
1364 				if(strstr_i(chval, s->string)) s->search_result=1;
1365 				break;
1366 
1367 			default:
1368 				fprintf(stderr, "Internal error: st_type of %d\n",s->value);
1369 				exit(255);
1370 			}
1371 
1372 		free_2(chval);
1373 		}
1374 	s=s->next;
1375 	}
1376 
1377 if(maxbase>fintim) return(MAX_HISTENT_TIME);
1378 
1379 DEBUG(printf("Maxbase: "TTFormat", total traces: %d\n",maxbase, totaltraces));
1380 s=GLOBALS->strace_ctx->straces;
1381 passcount=0;
1382 while(s)
1383 	{
1384 	DEBUG(printf("\tPass: %d, Name: %s\n",s->search_result, s->trace->name));
1385 	if(s->search_result) passcount++;
1386 	s=s->next;
1387 	}
1388 
1389 if(totaltraces)
1390 	{
1391 	if(GLOBALS->strace_ctx->logical_mutex[0])	/* and */
1392 		{
1393 		if(totaltraces==passcount) break;
1394 		}
1395 	else
1396 	if(GLOBALS->strace_ctx->logical_mutex[1])	/* or */
1397 		{
1398 		if(passcount) break;
1399 		}
1400 	else
1401 	if(GLOBALS->strace_ctx->logical_mutex[2])	/* xor */
1402 		{
1403 		if(passcount&1) break;
1404 		}
1405 	else
1406 	if(GLOBALS->strace_ctx->logical_mutex[3])	/* nand */
1407 		{
1408 		if(totaltraces!=passcount) break;
1409 		}
1410 	else
1411 	if(GLOBALS->strace_ctx->logical_mutex[4])	/* nor */
1412 		{
1413 		if(!passcount) break;
1414 		}
1415 	else
1416 	if(GLOBALS->strace_ctx->logical_mutex[5])	/* xnor */
1417 		{
1418 		if(!(passcount&1)) break;
1419 		}
1420 	}
1421 
1422 basetime=maxbase;
1423 }
1424 
1425 
1426 return(maxbase);
1427 }
1428 
1429 
strace_maketimetrace(int mode)1430 void strace_maketimetrace(int mode)
1431 {
1432 TimeType basetime=GLOBALS->tims.first;
1433 TimeType endtime =MAX_HISTENT_TIME;
1434 int notfirst=0;
1435 TimeType *t;
1436 int t_allocated;
1437 TimeType orig_basetime;
1438 
1439 if(GLOBALS->strace_ctx->timearray)
1440 	{
1441 	free_2(GLOBALS->strace_ctx->timearray);
1442 	GLOBALS->strace_ctx->timearray=NULL;
1443 	}
1444 
1445 GLOBALS->strace_ctx->timearray_size=0;
1446 
1447 if((!mode)&&(!GLOBALS->strace_ctx->shadow_active))
1448 	{
1449 	update_mark_count_label();
1450 	delete_mprintf();
1451 	return;	/* merely free stuff up */
1452 	}
1453 
1454 if(GLOBALS->strace_ctx->mark_idx_start>0)
1455 	{
1456 	if(GLOBALS->named_markers[GLOBALS->strace_ctx->mark_idx_start-1]>=0)
1457 		basetime=GLOBALS->named_markers[GLOBALS->strace_ctx->mark_idx_start-1];
1458 	else
1459 		{
1460 		char notused[129];
1461 		sprintf(notused, "%s not in use.\n", item_mark_start_strings[(unsigned int)GLOBALS->strace_ctx->mark_idx_start].str);
1462 		status_text(notused);
1463 		}
1464 	}
1465 
1466 if(GLOBALS->strace_ctx->mark_idx_end>0)
1467 	{
1468 	if(GLOBALS->named_markers[GLOBALS->strace_ctx->mark_idx_end-1]>=0)
1469 		endtime=GLOBALS->named_markers[GLOBALS->strace_ctx->mark_idx_end-1];
1470 	else
1471 		{
1472 		char notused[129];
1473 		sprintf(notused, "%s not in use.\n", item_mark_end_strings[(unsigned int)GLOBALS->strace_ctx->mark_idx_end].str);
1474 		status_text(notused);
1475 		}
1476 	}
1477 
1478 if(basetime>endtime)
1479 	{
1480 	TimeType tmp=basetime;
1481 	basetime    =endtime;
1482 	endtime     =tmp;
1483 	}
1484 
1485 t_allocated = 1;
1486 t = malloc_2(sizeof(TimeType) * t_allocated);
1487 
1488 orig_basetime = basetime;
1489 while(1)
1490 	{
1491 	basetime=strace_timetrace(basetime, notfirst);
1492 	notfirst=1;
1493 
1494 	if(endtime==MAX_HISTENT_TIME)
1495 		{
1496 		if(basetime==MAX_HISTENT_TIME) break;
1497 		}
1498 		else
1499 	   	{
1500 		if(basetime>endtime) break; /* formerly was >= which didn't mark the endpoint if true which is incorrect */
1501 		}			    /* i.e., if start is markable, end should be also */
1502 
1503 	if(basetime >= orig_basetime)
1504 		{
1505 		t[GLOBALS->strace_ctx->timearray_size] = basetime;
1506 		GLOBALS->strace_ctx->timearray_size++;
1507 		if(GLOBALS->strace_ctx->timearray_size == t_allocated)
1508 			{
1509 			t_allocated *= 2;
1510 			t = realloc_2(t, sizeof(TimeType) * t_allocated);
1511 			}
1512 		}
1513 	}
1514 
1515 if(GLOBALS->strace_ctx->timearray_size)
1516 	{
1517 	GLOBALS->strace_ctx->timearray = realloc_2(t, sizeof(TimeType) * GLOBALS->strace_ctx->timearray_size);
1518 	}
1519 	else
1520 	{
1521 	free_2(t);
1522 	GLOBALS->strace_ctx->timearray = NULL;
1523 	}
1524 
1525 if(!GLOBALS->strace_ctx->shadow_active) update_mark_count_label();
1526 }
1527 
1528 
1529 /*
1530  * swap context for mark during trace load...
1531  */
swap_strace_contexts(void)1532 void swap_strace_contexts(void)
1533 {
1534 struct strace *stemp;
1535 char logical_mutex_temp[6];
1536 char  mark_idx_start_temp, mark_idx_end_temp;
1537 
1538 stemp = GLOBALS->strace_ctx->straces;
1539 GLOBALS->strace_ctx->straces = GLOBALS->strace_ctx->shadow_straces;
1540 GLOBALS->strace_ctx->shadow_straces = stemp;
1541 
1542 memcpy(logical_mutex_temp, GLOBALS->strace_ctx->logical_mutex, 6);
1543 memcpy(GLOBALS->strace_ctx->logical_mutex, GLOBALS->strace_ctx->shadow_logical_mutex, 6);
1544 memcpy(GLOBALS->strace_ctx->shadow_logical_mutex, logical_mutex_temp, 6);
1545 
1546 mark_idx_start_temp   = GLOBALS->strace_ctx->mark_idx_start;
1547 GLOBALS->strace_ctx->mark_idx_start = GLOBALS->strace_ctx->shadow_mark_idx_start;
1548 GLOBALS->strace_ctx->shadow_mark_idx_start = mark_idx_start_temp;
1549 
1550 mark_idx_end_temp   = GLOBALS->strace_ctx->mark_idx_end;
1551 GLOBALS->strace_ctx->mark_idx_end = GLOBALS->strace_ctx->shadow_mark_idx_end;
1552 GLOBALS->strace_ctx->shadow_mark_idx_end = mark_idx_end_temp;
1553 }
1554 
1555 
1556 /*
1557  * delete context
1558  */
delete_strace_context(void)1559 void delete_strace_context(void)
1560 {
1561 int i;
1562 struct strace *stemp;
1563 struct strace *strace_cache;
1564 
1565 for(i=0;i<6;i++)
1566 	{
1567 	GLOBALS->strace_ctx->shadow_logical_mutex[i] = 0;
1568 	}
1569 
1570 GLOBALS->strace_ctx->shadow_mark_idx_start = 0;
1571 GLOBALS->strace_ctx->shadow_mark_idx_end   = 0;
1572 
1573 strace_cache = GLOBALS->strace_ctx->straces;	/* so the trace actually deletes */
1574 GLOBALS->strace_ctx->straces=NULL;
1575 
1576 stemp = GLOBALS->strace_ctx->shadow_straces;
1577 while(stemp)
1578 	{
1579 	GLOBALS->strace_ctx->shadow_straces = stemp->next;
1580 	if(stemp->string) free_2(stemp->string);
1581 
1582 	FreeTrace(stemp->trace);
1583 	free_2(stemp);
1584 	stemp = GLOBALS->strace_ctx->shadow_straces;
1585 	}
1586 
1587 if(GLOBALS->strace_ctx->shadow_string)
1588 	{
1589 	free_2(GLOBALS->strace_ctx->shadow_string);
1590 	GLOBALS->strace_ctx->shadow_string = NULL;
1591 	}
1592 
1593 GLOBALS->strace_ctx->straces = strace_cache;
1594 }
1595 
1596 /*************************************************************************/
1597 
1598 /*
1599  * printf to memory..
1600  */
1601 
mprintf(const char * fmt,...)1602 int mprintf(const char *fmt, ... )
1603 {
1604 int len;
1605 int rc;
1606 va_list args;
1607 struct mprintf_buff_t *bt = (struct mprintf_buff_t *)calloc_2(1, sizeof(struct mprintf_buff_t));
1608 char buff[65537];
1609 
1610 va_start(args, fmt);
1611 rc=vsprintf(buff, fmt, args);
1612 len = strlen(buff);
1613 bt->str = malloc_2(len+1);
1614 strcpy(bt->str, buff);
1615 
1616 if(!GLOBALS->strace_ctx->mprintf_buff_current)
1617         {
1618         GLOBALS->strace_ctx->mprintf_buff_head = GLOBALS->strace_ctx->mprintf_buff_current = bt;
1619         }
1620         else
1621         {
1622         GLOBALS->strace_ctx->mprintf_buff_current->next = bt;
1623         GLOBALS->strace_ctx->mprintf_buff_current = bt;
1624         }
1625 
1626 va_end(args);
1627 return(rc);
1628 }
1629 
1630 /*
1631  * kill mprint buffer
1632  */
delete_mprintf(void)1633 void delete_mprintf(void)
1634 {
1635 if(GLOBALS->strace_ctx->mprintf_buff_head)
1636 	{
1637 	struct mprintf_buff_t *mb = GLOBALS->strace_ctx->mprintf_buff_head;
1638 	struct mprintf_buff_t *mbt;
1639 
1640 	while(mb)
1641 		{
1642 		free_2(mb->str);
1643 		mbt = mb->next;
1644 		free_2(mb);
1645 		mb = mbt;
1646 		}
1647 
1648 	GLOBALS->strace_ctx->mprintf_buff_head = GLOBALS->strace_ctx->mprintf_buff_current = NULL;
1649 	}
1650 }
1651 
1652 
1653 /*
1654  * so we can (later) write out the traces which are actually marked...
1655  */
cache_actual_pattern_mark_traces(void)1656 void cache_actual_pattern_mark_traces(void)
1657 {
1658 Trptr t;
1659 TraceFlagsType def=0;
1660 TimeType prevshift=LLDescriptor(0);
1661 struct strace *st;
1662 
1663 delete_mprintf();
1664 
1665 if(GLOBALS->strace_ctx->timearray)
1666 	{
1667 	mprintf("!%d%d%d%d%d%d%c%c\n", GLOBALS->strace_ctx->logical_mutex[0], GLOBALS->strace_ctx->logical_mutex[1], GLOBALS->strace_ctx->logical_mutex[2], GLOBALS->strace_ctx->logical_mutex[3], GLOBALS->strace_ctx->logical_mutex[4], GLOBALS->strace_ctx->logical_mutex[5], '@'+GLOBALS->strace_ctx->mark_idx_start, '@'+GLOBALS->strace_ctx->mark_idx_end);
1668 	st=GLOBALS->strace_ctx->straces;
1669 
1670 	while(st)
1671 		{
1672 		if(st->value==ST_STRING)
1673 			{
1674 			mprintf("?\"%s\n", st->string ? st->string : ""); /* search type for this trace is string.. */
1675 			}
1676 			else
1677 			{
1678 			mprintf("?%02x\n", (unsigned char)st->value);	/* else search type for this trace.. */
1679 			}
1680 
1681 		t=st->trace;
1682 
1683 		if((t->flags!=def)||(st==GLOBALS->strace_ctx->straces))
1684 			{
1685 			mprintf("@%"TRACEFLAGSPRIFMT"\n",def=t->flags);
1686 			}
1687 
1688 		if((t->shift)||((prevshift)&&(!t->shift)))
1689 			{
1690 			mprintf(">"TTFormat"\n", t->shift);
1691 			}
1692 		prevshift=t->shift;
1693 
1694 		if(!(t->flags&(TR_BLANK|TR_ANALOG_BLANK_STRETCH)))
1695 			{
1696 			if(t->vector)
1697 				{
1698 				int i;
1699 				nptr *nodes;
1700 
1701 				if(HasAlias(t)) { mprintf("+{%s} ",t->name_full); }
1702 
1703 				mprintf("#{%s}",t->name);
1704 
1705 				nodes=t->n.vec->bits->nodes;
1706 				for(i=0;i<t->n.vec->bits->nnbits;i++)
1707 					{
1708 					int was_packed = HIER_DEPACK_STATIC;
1709 					char *namex;
1710 					if(nodes[i]->expansion)
1711 						{
1712 						namex = hier_decompress_flagged(nodes[i]->expansion->parent->nname, &was_packed);
1713 						mprintf(" (%d)%s",nodes[i]->expansion->parentbit, namex);
1714 						/* if(was_packed) free_2(namex); ...not needed for HIER_DEPACK_STATIC */
1715 						}
1716 						else
1717 						{
1718 						/* namex = */ hier_decompress_flagged(nodes[i]->nname, &was_packed); /* scan-build */
1719 						mprintf(" %s",nodes[i]->nname);
1720 						/* if(was_packed) free_2(namex); ...not needed for HIER_DEPACK_STATIC */
1721 						}
1722 					}
1723 				mprintf("\n");
1724 				}
1725 				else
1726 				{
1727 				int was_packed = HIER_DEPACK_STATIC;
1728 				char *namex;
1729 
1730 				if(HasAlias(t))
1731 					{
1732 					if(t->n.nd->expansion)
1733 						{
1734 						namex = hier_decompress_flagged(t->n.nd->expansion->parent->nname, &was_packed);
1735 						mprintf("+{%s} (%d)%s\n",t->name+2,t->n.nd->expansion->parentbit, namex);
1736 						/* if(was_packed) free_2(namex); ...not needed for HIER_DEPACK_STATIC */
1737 						}
1738 						else
1739 						{
1740 						namex = hier_decompress_flagged(t->n.nd->nname, &was_packed);
1741 						mprintf("+{%s} %s\n",t->name+2,namex);
1742 						/* if(was_packed) free_2(namex); ...not needed for HIER_DEPACK_STATIC */
1743 						}
1744 					}
1745 					else
1746 					{
1747 					if(t->n.nd->expansion)
1748 						{
1749 						namex = hier_decompress_flagged(t->n.nd->expansion->parent->nname, &was_packed);
1750 						mprintf("(%d)%s\n",t->n.nd->expansion->parentbit, namex);
1751 						/* if(was_packed) free_2(namex); ...not needed for HIER_DEPACK_STATIC */
1752 						}
1753 						else
1754 						{
1755 						namex = hier_decompress_flagged(t->n.nd->nname, &was_packed);
1756 						mprintf("%s\n",namex);
1757 						/* if(was_packed) free_2(namex); ...not needed for HIER_DEPACK_STATIC*/
1758 						}
1759 					}
1760 				}
1761 			}
1762 
1763 		st=st->next;
1764 		} /* while(st)... */
1765 
1766 	mprintf("!!\n");	/* mark end of strace region */
1767 	}
1768 }
1769 
1770