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