1 /*
2  * Copyright (c) Tony Bybell 2010-2014.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  */
9 
10 #include "globals.h"
11 #include <config.h>
12 #include <gtk/gtk.h>
13 #include "gtk12compat.h"
14 #include "symbol.h"
15 #include "ttranslate.h"
16 #include "pipeio.h"
17 #include "debug.h"
18 
19 #ifdef _MSC_VER
20 #define strcasecmp _stricmp
21 #endif
22 
args_entry_callback(GtkWidget * widget,GtkWidget * entry)23 static void args_entry_callback(GtkWidget *widget, GtkWidget *entry)
24 {
25 (void)widget;
26 
27 G_CONST_RETURN gchar *entry_text;
28 
29 entry_text=gtk_entry_get_text(GTK_ENTRY(entry));
30 entry_text = entry_text ? entry_text : "";
31 
32 if(GLOBALS->ttranslate_args)
33 	{
34 	free_2(GLOBALS->ttranslate_args);
35 	}
36 GLOBALS->ttranslate_args = strdup_2(entry_text);
37 
38 DEBUG(printf("Args Entry contents: %s\n",entry_text));
39 }
40 
41 
init_ttrans_data(void)42 void init_ttrans_data(void)
43 {
44 int i;
45 
46 if(!GLOBALS->ttranssel_filter) { GLOBALS->ttranssel_filter = calloc_2(TTRANS_FILTER_MAX+1, sizeof(char *)); }
47 if(!GLOBALS->ttrans_filter) { GLOBALS->ttrans_filter = calloc_2(TTRANS_FILTER_MAX+1, sizeof(struct pipe_ctx *)); }
48 
49 for(i=0;i<TTRANS_FILTER_MAX+1;i++)
50 	{
51 	GLOBALS->ttranssel_filter[i] = NULL;
52 	GLOBALS->ttrans_filter[i] = NULL;
53 	}
54 }
55 
remove_all_ttrans_filters(void)56 void remove_all_ttrans_filters(void)
57 {
58 struct Global *GLOBALS_cache = GLOBALS;
59 unsigned int i, j;
60 
61 for(j=0;j<GLOBALS->num_notebook_pages;j++)
62         {
63         GLOBALS = (*GLOBALS->contexts)[j];
64 
65 	for(i=1;i<TTRANS_FILTER_MAX+1;i++)
66 		{
67 		if(GLOBALS->ttrans_filter[i])
68 			{
69 			pipeio_destroy(GLOBALS->ttrans_filter[i]);
70 			GLOBALS->ttrans_filter[i] = NULL;
71 			}
72 
73 		if(GLOBALS->ttranssel_filter[i])
74 			{
75 			free_2(GLOBALS->ttranssel_filter[i]);
76 			GLOBALS->ttranssel_filter[i] = NULL;
77 			}
78 		}
79 
80 	GLOBALS = GLOBALS_cache;
81 	}
82 }
83 
84 
85 int traverse_vector_nodes(Trptr t);
86 
regen_display(void)87 static void regen_display(void)
88 {
89 if(GLOBALS->signalarea && GLOBALS->wavearea)
90 	{
91 	GLOBALS->signalwindow_width_dirty=1;
92 	MaxSignalLength();
93 	signalarea_configure_event(GLOBALS->signalarea, NULL);
94 	wavearea_configure_event(GLOBALS->wavearea, NULL);
95 	}
96 }
97 
98 
99 /*
100  * this is likely obsolete
101  */
102 #if 0
103 static void remove_ttrans_filter(int which, int regen)
104 {
105 if(GLOBALS->ttrans_filter[which])
106 	{
107 	pipeio_destroy(GLOBALS->ttrans_filter[which]);
108 	GLOBALS->ttrans_filter[which] = NULL;
109 
110 	if(regen)
111 	        {
112 		regen_display();
113 	        }
114 	}
115 }
116 #endif
117 
load_ttrans_filter(int which,char * name)118 static void load_ttrans_filter(int which, char *name)
119 {
120 
121   FILE *stream;
122 
123   char *cmd;
124   char exec_name[1025];
125   char abs_path [1025];
126   char* arg, end;
127   int result;
128 
129   exec_name[0] = 0;
130   abs_path[0]  = 0;
131 
132   /* if name has arguments grab only the first word (the name of the executable)*/
133   sscanf(name, "%s ", exec_name);
134 
135   arg = name + strlen(exec_name);
136 
137   /* remove leading spaces from argument */
138   while (isspace((int)(unsigned char)arg[0])) {
139     arg++;
140   }
141 
142   /* remove trailing spaces from argument */
143   if (strlen(arg) > 0) {
144 
145     end = strlen(arg) - 1;
146 
147     while (arg[(int)end] == ' ') {
148       arg[(int)end] = 0;
149       end--;
150     }
151   }
152 
153   /* turn the exec_name into an absolute path */
154 #if !defined __MINGW32__ && !defined _MSC_VER
155   cmd = (char *)malloc_2(strlen(exec_name)+6+1);
156   sprintf(cmd, "which %s", exec_name);
157   stream = popen(cmd, "r");
158 
159   result = fscanf(stream, "%s", abs_path);
160 
161   if((strlen(abs_path) == 0)||(!result))
162     {
163       status_text("Could not find transaction filter process!\n");
164       pclose(stream); /* cppcheck */
165       return;
166 
167     }
168 
169   pclose(stream);
170   free_2(cmd);
171 #else
172   strcpy(abs_path, exec_name);
173 #endif
174 
175   /* remove_ttrans_filter(which, 0); ... should never happen from GUI, but perhaps possible from save files or other weirdness */
176   if(!GLOBALS->ttrans_filter[which])
177 	{
178   	GLOBALS->ttrans_filter[which] = pipeio_create(abs_path, arg);
179 	}
180 }
181 
install_ttrans_filter(int which)182 int install_ttrans_filter(int which)
183 {
184 int found = 0;
185 
186 if((which<0)||(which>=(PROC_FILTER_MAX+1)))
187         {
188         which = 0;
189         }
190 
191 if(GLOBALS->traces.first)
192         {
193         Trptr t = GLOBALS->traces.first;
194         while(t)
195                 {
196                 if(t->flags&TR_HIGHLIGHT)
197                         {
198 			if((!t->vector) && (which))
199 				{
200 				bvptr v = combine_traces(1, t); /* down: make single signal a vector */
201 				if(v)
202 					{
203 					v->transaction_nd = t->n.nd; /* cache for savefile, disable */
204 					t->vector = 1;
205 					t->n.vec = v;		/* splice in */
206 					}
207 				}
208 
209                         if((t->vector) && (!(t->flags&(TR_BLANK|TR_ANALOG_BLANK_STRETCH))))
210                                 {
211                                 t->t_filter = which;
212 				t->t_filter_converted = 0;
213 
214 				/* back out allocation to revert (if any) */
215 				if(t->n.vec->transaction_cache)
216 					{
217 					int i;
218 					bvptr bv = t->n.vec;
219 					bvptr bv2;
220 					nptr ndcache = NULL;
221 
222 					t->n.vec = bv->transaction_cache;
223 					if((t->n.vec->transaction_nd) && (!which))
224 						{
225 						ndcache = t->n.vec->transaction_nd;
226 						}
227 
228 					while(bv)
229 						{
230 						bv2 = bv->transaction_chain;
231 
232 						if(bv->bvname)
233 							{
234 							free_2(bv->bvname);
235 							}
236 
237 						for(i=0;i<bv->numregions;i++)
238 							{
239 							free_2(bv->vectors[i]);
240 							}
241 
242 						free_2(bv);
243 						bv = bv2;
244 						}
245 
246 					t->name = t->n.vec->bvname;
247 	                  		if(GLOBALS->hier_max_level)
248 	                    			t->name = hier_extract(t->name, GLOBALS->hier_max_level);
249 
250 					if(ndcache)
251 						{
252 						t->n.nd = ndcache;
253 						t->vector = 0;
254 						/* still need to deallocate old t->n.vec! */
255 						}
256 					}
257 
258 				if(!which)
259 					{
260 					t->flags &= (~(TR_TTRANSLATED|TR_ANALOGMASK));
261 					}
262 					else
263 					{
264 					t->flags &= (~(TR_ANALOGMASK));
265 					t->flags |= TR_TTRANSLATED;
266 					if(t->transaction_args) free_2(t->transaction_args);
267 					if(GLOBALS->ttranslate_args)
268 						{
269 						t->transaction_args = strdup_2(GLOBALS->ttranslate_args);
270 						}
271 						else
272 						{
273 						t->transaction_args = NULL;
274 						}
275 					traverse_vector_nodes(t);
276 					}
277                                 found++;
278 
279 				if(t->t_match)
280 					{
281 					Trptr curr_trace = t;
282 					t = t->t_next;
283 					while(t && (t->t_match != curr_trace))
284 						{
285 						t = t->t_next;
286 						}
287 					}
288                                 }
289                         }
290                 t=GiveNextTrace(t);
291                 }
292         }
293 
294 if(found)
295 	{
296 	regen_display();
297 	}
298 
299 return(found);
300 }
301 
302 /************************************************************************/
303 
304 
305 
destroy_callback(GtkWidget * widget,GtkWidget * nothing)306 static void destroy_callback(GtkWidget *widget, GtkWidget *nothing)
307 {
308 (void)widget;
309 (void)nothing;
310 
311 GLOBALS->is_active_ttranslate_c_2=0;
312 gtk_widget_destroy(GLOBALS->window_ttranslate_c_5);
313 GLOBALS->window_ttranslate_c_5 = NULL;
314 }
315 
ok_callback(GtkWidget * widget,GtkWidget * nothing)316 static void ok_callback(GtkWidget *widget, GtkWidget *nothing)
317 {
318 install_ttrans_filter(GLOBALS->current_filter_ttranslate_c_1);
319 destroy_callback(widget, nothing);
320 }
321 
select_row_callback(GtkWidget * widget,gint row,gint column,GdkEventButton * event,gpointer data)322 static void select_row_callback(GtkWidget *widget, gint row, gint column,
323 	GdkEventButton *event, gpointer data)
324 {
325 (void)widget;
326 (void)column;
327 (void)event;
328 (void)data;
329 
330 GLOBALS->current_filter_ttranslate_c_1 = row + 1;
331 }
332 
unselect_row_callback(GtkWidget * widget,gint row,gint column,GdkEventButton * event,gpointer data)333 static void unselect_row_callback(GtkWidget *widget, gint row, gint column,
334 	GdkEventButton *event, gpointer data)
335 {
336 (void)widget;
337 (void)row;
338 (void)column;
339 (void)event;
340 (void)data;
341 
342 GLOBALS->current_filter_ttranslate_c_1 = 0; /* none */
343 }
344 
345 
add_filter_callback_2(GtkWidget * widget,GtkWidget * nothing)346 static void add_filter_callback_2(GtkWidget *widget, GtkWidget *nothing)
347 {
348 (void)widget;
349 (void)nothing;
350 
351 int i;
352 GtkCList *cl;
353 
354 if(!GLOBALS->filesel_ok) { return; }
355 
356 if(*GLOBALS->fileselbox_text)
357 	{
358 	for(i=0;i<GLOBALS->num_ttrans_filters;i++)
359 		{
360 		if(GLOBALS->ttranssel_filter[i])
361 			{
362 			if(!strcmp(GLOBALS->ttranssel_filter[i], *GLOBALS->fileselbox_text))
363 				{
364 				status_text("Filter already imported.\n");
365 				if(GLOBALS->is_active_ttranslate_c_2) gdk_window_raise(GLOBALS->window_ttranslate_c_5->window);
366 				return;
367 				}
368 			}
369 		}
370 	}
371 
372 GLOBALS->num_ttrans_filters++;
373 load_ttrans_filter(GLOBALS->num_ttrans_filters, *GLOBALS->fileselbox_text);
374 if(GLOBALS->ttrans_filter[GLOBALS->num_ttrans_filters])
375 	{
376 	if(GLOBALS->ttranssel_filter[GLOBALS->num_ttrans_filters]) free_2(GLOBALS->ttranssel_filter[GLOBALS->num_ttrans_filters]);
377 	GLOBALS->ttranssel_filter[GLOBALS->num_ttrans_filters] = malloc_2(strlen(*GLOBALS->fileselbox_text) + 1);
378 	strcpy(GLOBALS->ttranssel_filter[GLOBALS->num_ttrans_filters], *GLOBALS->fileselbox_text);
379 
380 	cl=GTK_CLIST(GLOBALS->clist_ttranslate_c_2);
381 	gtk_clist_freeze(cl);
382 	gtk_clist_append(cl,(gchar **)&(GLOBALS->ttranssel_filter[GLOBALS->num_ttrans_filters]));
383 
384 	gtk_clist_set_column_width(cl,0,gtk_clist_optimal_column_width(cl,0));
385 	gtk_clist_thaw(cl);
386 	}
387 	else
388 	{
389 	GLOBALS->num_ttrans_filters--;
390 	}
391 
392 if(GLOBALS->is_active_ttranslate_c_2) gdk_window_raise(GLOBALS->window_ttranslate_c_5->window);
393 }
394 
add_filter_callback(GtkWidget * widget,GtkWidget * nothing)395 static void add_filter_callback(GtkWidget *widget, GtkWidget *nothing)
396 {
397 (void)widget;
398 (void)nothing;
399 
400 if(GLOBALS->num_ttrans_filters == TTRANS_FILTER_MAX)
401 	{
402 	status_text("Max number of transaction filters processes installed already.\n");
403 	return;
404 	}
405 
406 fileselbox("Select Transaction Filter Process",&GLOBALS->fcurr_ttranslate_c_1,GTK_SIGNAL_FUNC(add_filter_callback_2), GTK_SIGNAL_FUNC(NULL),"*", 0);
407 }
408 
409 /*
410  * mainline..
411  */
ttrans_searchbox(char * title)412 void ttrans_searchbox(char *title)
413 {
414     int i;
415 
416     GtkWidget *scrolled_win;
417     GtkWidget *vbox1, *hbox, *hbox0;
418     GtkWidget *button1, *button5, *button6;
419     gchar *titles[]={"Transaction Process Filter Select"};
420     GtkWidget *frame2, *frameh, *frameh0;
421     GtkWidget *table;
422     GtkTooltips *tooltips;
423     GtkWidget *label;
424     GtkWidget *entry;
425 
426     if(GLOBALS->is_active_ttranslate_c_2)
427 	{
428 	gdk_window_raise(GLOBALS->window_ttranslate_c_5->window);
429 	return;
430 	}
431 
432     GLOBALS->is_active_ttranslate_c_2=1;
433     GLOBALS->current_filter_ttranslate_c_1 = 0;
434 
435     /* create a new modal window */
436     GLOBALS->window_ttranslate_c_5 = gtk_window_new(GLOBALS->disable_window_manager ? GTK_WINDOW_POPUP : GTK_WINDOW_TOPLEVEL);
437     install_focus_cb(GLOBALS->window_ttranslate_c_5, ((char *)&GLOBALS->window_ttranslate_c_5) - ((char *)GLOBALS));
438 
439     gtk_window_set_title(GTK_WINDOW (GLOBALS->window_ttranslate_c_5), title);
440     gtkwave_signal_connect(GTK_OBJECT (GLOBALS->window_ttranslate_c_5), "delete_event",(GtkSignalFunc) destroy_callback, NULL);
441 
442     tooltips=gtk_tooltips_new_2();
443 
444     table = gtk_table_new (256, 1, FALSE);
445     gtk_widget_show (table);
446 
447     vbox1 = gtk_vbox_new (FALSE, 0);
448     gtk_container_border_width (GTK_CONTAINER (vbox1), 3);
449     gtk_widget_show (vbox1);
450 
451 
452     frame2 = gtk_frame_new (NULL);
453     gtk_container_border_width (GTK_CONTAINER (frame2), 3);
454     gtk_widget_show(frame2);
455 
456     gtk_table_attach (GTK_TABLE (table), frame2, 0, 1, 0, 253,
457                         GTK_FILL | GTK_EXPAND,
458                         GTK_FILL | GTK_EXPAND | GTK_SHRINK, 1, 1);
459 
460     GLOBALS->clist_ttranslate_c_2=gtk_clist_new_with_titles(1,titles);
461     gtk_clist_column_titles_passive(GTK_CLIST(GLOBALS->clist_ttranslate_c_2));
462 
463     gtk_clist_set_selection_mode(GTK_CLIST(GLOBALS->clist_ttranslate_c_2), GTK_SELECTION_EXTENDED);
464     gtkwave_signal_connect_object (GTK_OBJECT (GLOBALS->clist_ttranslate_c_2), "select_row",GTK_SIGNAL_FUNC(select_row_callback),NULL);
465     gtkwave_signal_connect_object (GTK_OBJECT (GLOBALS->clist_ttranslate_c_2), "unselect_row",GTK_SIGNAL_FUNC(unselect_row_callback),NULL);
466 
467     for(i=0;i<GLOBALS->num_ttrans_filters;i++)
468 	{
469 	gtk_clist_append(GTK_CLIST(GLOBALS->clist_ttranslate_c_2),(gchar **)&(GLOBALS->ttranssel_filter[i+1]));
470 	}
471     gtk_clist_set_column_width(GTK_CLIST(GLOBALS->clist_ttranslate_c_2),0,gtk_clist_optimal_column_width(GTK_CLIST(GLOBALS->clist_ttranslate_c_2),0));
472 
473     gtk_widget_show (GLOBALS->clist_ttranslate_c_2);
474 
475     scrolled_win = gtk_scrolled_window_new (NULL, NULL);
476     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
477                                       GTK_POLICY_AUTOMATIC,
478                                       GTK_POLICY_AUTOMATIC);
479     gtk_widget_set_usize( GTK_WIDGET (scrolled_win), -1, 300);
480     gtk_widget_show(scrolled_win);
481 
482     /* gtk_scrolled_window_add_with_viewport doesn't seen to work right here.. */
483     gtk_container_add (GTK_CONTAINER (scrolled_win), GLOBALS->clist_ttranslate_c_2);
484 
485     gtk_container_add (GTK_CONTAINER (frame2), scrolled_win);
486 
487 
488     frameh0 = gtk_frame_new (NULL);
489     gtk_container_border_width (GTK_CONTAINER (frameh0), 3);
490     gtk_widget_show(frameh0);
491     gtk_table_attach (GTK_TABLE (table), frameh0, 0, 1, 253, 254,
492                         GTK_FILL | GTK_EXPAND,
493                         GTK_FILL | GTK_EXPAND | GTK_SHRINK, 1, 1);
494 
495 
496     hbox0 = gtk_hbox_new (FALSE, 1);
497     gtk_widget_show (hbox0);
498 
499     button6 = gtk_button_new_with_label (" Add Trans Filter to List ");
500     gtk_container_border_width (GTK_CONTAINER (button6), 3);
501     gtkwave_signal_connect_object (GTK_OBJECT (button6), "clicked",GTK_SIGNAL_FUNC(add_filter_callback),GTK_OBJECT (GLOBALS->window_ttranslate_c_5));
502     gtk_widget_show (button6);
503     gtk_tooltips_set_tip_2(tooltips, button6,
504 		"Bring up a file requester to add a transaction process filter to the filter select window.",NULL);
505 
506     gtk_box_pack_start (GTK_BOX (hbox0), button6, TRUE, FALSE, 0);
507     gtk_container_add (GTK_CONTAINER (frameh0), hbox0);
508 
509     	/* args entry box */
510 	{
511 	Trptr t=GLOBALS->traces.first;
512 	while(t)
513 	        {
514 		if(t->flags&TR_HIGHLIGHT)
515 			{
516 			if(t->transaction_args)
517 				{
518 				if(GLOBALS->ttranslate_args) free_2(GLOBALS->ttranslate_args);
519 				GLOBALS->ttranslate_args = strdup_2(t->transaction_args);
520 				break;
521 				}
522 	                }
523 
524 	        t=t->t_next;
525 	        }
526 
527     	frameh0 = gtk_frame_new (NULL);
528     	gtk_container_border_width (GTK_CONTAINER (frameh0), 3);
529     	gtk_widget_show(frameh0);
530     	gtk_table_attach (GTK_TABLE (table), frameh0, 0, 1, 254, 255,
531                         GTK_FILL | GTK_EXPAND,
532                         GTK_FILL | GTK_EXPAND | GTK_SHRINK, 1, 1);
533 
534 	label=gtk_label_new("Args:");
535 	entry=gtk_entry_new_with_max_length(1025);
536 
537 	gtk_entry_set_text(GTK_ENTRY(entry), GLOBALS->ttranslate_args ? GLOBALS->ttranslate_args : "");
538 	gtk_signal_connect (GTK_OBJECT (entry), "activate",GTK_SIGNAL_FUNC (args_entry_callback), entry);
539 	gtk_signal_connect (GTK_OBJECT (entry), "changed",GTK_SIGNAL_FUNC (args_entry_callback), entry);
540 	hbox0=gtk_hbox_new(FALSE, 0);
541 	gtk_box_pack_start(GTK_BOX(hbox0), label, FALSE, FALSE, 0);
542 	gtk_widget_show(label);
543 	gtk_box_pack_start(GTK_BOX(hbox0), entry, TRUE, TRUE, 0);
544 	gtk_widget_show(entry);
545 	gtk_widget_show(hbox0);
546 
547 	gtk_container_add (GTK_CONTAINER (frameh0), hbox0);
548 	}
549 
550     /* bottom OK/Cancel part */
551     frameh = gtk_frame_new (NULL);
552     gtk_container_border_width (GTK_CONTAINER (frameh), 3);
553     gtk_widget_show(frameh);
554     gtk_table_attach (GTK_TABLE (table), frameh, 0, 1, 255, 256,
555                         GTK_FILL | GTK_EXPAND,
556                         GTK_FILL | GTK_EXPAND | GTK_SHRINK, 1, 1);
557 
558 
559     hbox = gtk_hbox_new (FALSE, 1);
560     gtk_widget_show (hbox);
561 
562     button1 = gtk_button_new_with_label (" OK ");
563     gtk_container_border_width (GTK_CONTAINER (button1), 3);
564     gtkwave_signal_connect_object (GTK_OBJECT (button1), "clicked",GTK_SIGNAL_FUNC(ok_callback),GTK_OBJECT (GLOBALS->window_ttranslate_c_5));
565     gtk_widget_show (button1);
566     gtk_tooltips_set_tip_2(tooltips, button1,
567 		"Add selected signals to end of the display on the main window.",NULL);
568 
569     gtk_box_pack_start (GTK_BOX (hbox), button1, TRUE, FALSE, 0);
570 
571     button5 = gtk_button_new_with_label (" Cancel ");
572     gtk_container_border_width (GTK_CONTAINER (button5), 3);
573     gtkwave_signal_connect_object (GTK_OBJECT (button5), "clicked",GTK_SIGNAL_FUNC(destroy_callback),GTK_OBJECT (GLOBALS->window_ttranslate_c_5));
574     gtk_tooltips_set_tip_2(tooltips, button5,
575 		"Do nothing and return to the main window.",NULL);
576     gtk_widget_show (button5);
577     gtk_box_pack_start (GTK_BOX (hbox), button5, TRUE, FALSE, 0);
578 
579     gtk_container_add (GTK_CONTAINER (frameh), hbox);
580     gtk_container_add (GTK_CONTAINER (GLOBALS->window_ttranslate_c_5), table);
581 
582     gtk_widget_set_usize(GTK_WIDGET(GLOBALS->window_ttranslate_c_5), 400, 400);
583     gtk_widget_show(GLOBALS->window_ttranslate_c_5);
584 }
585 
586 
587 /*
588  * currently only called by parsewavline
589  */
set_current_translate_ttrans(char * name)590 void set_current_translate_ttrans(char *name)
591 {
592 int i;
593 
594 for(i=1;i<GLOBALS->num_ttrans_filters+1;i++)
595 	{
596 	if(!strcmp(GLOBALS->ttranssel_filter[i], name)) { GLOBALS->current_translate_ttrans = i; return; }
597 	}
598 
599 if(GLOBALS->num_ttrans_filters < TTRANS_FILTER_MAX)
600 	{
601 	GLOBALS->num_ttrans_filters++;
602 	load_ttrans_filter(GLOBALS->num_ttrans_filters, name);
603 	if(!GLOBALS->ttrans_filter[GLOBALS->num_ttrans_filters])
604 		{
605 		GLOBALS->num_ttrans_filters--;
606 		GLOBALS->current_translate_ttrans = 0;
607 		}
608 		else
609 		{
610 		if(GLOBALS->ttranssel_filter[GLOBALS->num_ttrans_filters]) free_2(GLOBALS->ttranssel_filter[GLOBALS->num_ttrans_filters]);
611 		GLOBALS->ttranssel_filter[GLOBALS->num_ttrans_filters] = malloc_2(strlen(name) + 1);
612 		strcpy(GLOBALS->ttranssel_filter[GLOBALS->num_ttrans_filters], name);
613 		GLOBALS->current_translate_ttrans = GLOBALS->num_ttrans_filters;
614 		}
615 	}
616 }
617 
618 
traverse_vector_nodes(Trptr t)619 int traverse_vector_nodes(Trptr t)
620 {
621 int i;
622 int cvt_ok = 0;
623 
624 if((t->t_filter) && (t->flags & TR_TTRANSLATED) && (t->vector) && (!t->t_filter_converted))
625 	{
626 #if !defined _MSC_VER && !defined __MINGW32__
627 	int rc = save_nodes_to_trans(GLOBALS->ttrans_filter[t->t_filter]->sout, t);
628 #else
629 	int rc = save_nodes_to_trans((FILE *)(GLOBALS->ttrans_filter[t->t_filter]->g_hChildStd_IN_Wr), t);
630 #endif
631 
632 	if(rc == VCDSAV_OK)
633 		{
634 		int is_finish = 0;
635 		bvptr prev_transaction_trace = NULL;
636 
637 		while(!is_finish)
638 			{
639 			struct VectorEnt *vt_head = NULL, *vt_curr = NULL;
640 			struct VectorEnt *vt;
641 			struct VectorEnt *vprev;
642 			bvptr bv;
643 			int regions = 2;
644 			TimeType prev_tim = LLDescriptor(-1);
645 			char *trace_name = NULL;
646 			char *orig_name = t->n.vec->bvname;
647 
648 			cvt_ok = 1;
649 
650 			vt_head = vt_curr = vt = calloc_2(1, sizeof(struct VectorEnt) + 1);
651 			vt->time = LLDescriptor(-2);
652 			vprev = vt; /* for duplicate removal */
653 
654 			vt_curr = vt_curr->next = vt = calloc_2(1, sizeof(struct VectorEnt) + 1);
655 			vt->time = LLDescriptor(-1);
656 
657 			for(;;)
658 				{
659 				char buf[1025];
660 				char *pnt, *rtn;
661 
662 #if !defined _MSC_VER && !defined __MINGW32__
663 				if(feof(GLOBALS->ttrans_filter[t->t_filter]->sin)) break; /* should never happen */
664 
665 				buf[0] = 0;
666 				pnt = fgets(buf, 1024, GLOBALS->ttrans_filter[t->t_filter]->sin);
667 				if(!pnt) break;
668 				rtn = pnt;
669 				while(*rtn)
670 					{
671 					if((*rtn == '\n') || (*rtn == '\r')) { *rtn = 0; break; }
672 					rtn++;
673 					}
674 #else
675 			        {
676 			        BOOL bSuccess;
677 			        DWORD dwRead;
678 				int n;
679 
680 			        for(n=0;n<1024;n++)
681 			                {
682 			                do      {
683 			                        bSuccess = ReadFile(GLOBALS->ttrans_filter[t->t_filter]->g_hChildStd_OUT_Rd, buf+n, 1, &dwRead, NULL);
684 			                        if((!bSuccess)||(buf[n]=='\n'))
685 			                                {
686 			                                goto ex;
687 			                                }
688 
689 			                        } while(buf[n]=='\r');
690 			                }
691 ex:     			buf[n] = 0;
692 				pnt = buf;
693 			        }
694 #endif
695 
696 
697 				while(*pnt) { if(isspace((int)(unsigned char)*pnt)) pnt++; else break;}
698 
699 				if(*pnt=='#')
700 					{
701 					TimeType tim = atoi_64(pnt+1) * GLOBALS->time_scale;
702 					int slen;
703 					char *sp;
704 
705 					while(*pnt) { if(!isspace((int)(unsigned char)*pnt)) pnt++; else break; }
706 					while(*pnt) { if(isspace((int)(unsigned char)*pnt)) pnt++; else break; }
707 
708 					sp = pnt;
709 					slen = strlen(sp);
710 
711 					if(slen)
712 						{
713 						pnt = sp + slen - 1;
714 						do
715 							{
716 							if(isspace((int)(unsigned char)*pnt)) { *pnt = 0; pnt--; slen--; } else { break; }
717 							} while(pnt != (sp-1));
718 						}
719 
720 					vt = calloc_2(1, sizeof(struct VectorEnt) + slen + 1);
721 					if(sp) strcpy((char *)vt->v, sp);
722 
723 					if(tim > prev_tim)
724 						{
725 						prev_tim = vt->time = tim;
726 						vt_curr->next = vt;
727 						vt_curr = vt;
728 						vprev = vprev->next; /* bump forward the -2 node pointer */
729 						regions++;
730 						}
731 					else if(tim == prev_tim)
732 						{
733 						vt->time = prev_tim;
734 						free_2(vt_curr);
735 						vt_curr = vprev->next = vt; /* splice new one in -1 node place */
736 						}
737 					else
738 						{
739 						free_2(vt); /* throw it away */
740 						}
741 
742 					continue;
743 					}
744 				else
745 				if((*pnt=='M')||(*pnt=='m'))
746 					{
747 					int mlen;
748 					pnt++;
749 
750 					mlen = bijective_marker_id_string_len(pnt);
751 					if(mlen)
752 						{
753 						int which_marker = bijective_marker_id_string_hash(pnt);
754 						if((which_marker >= 0) && (which_marker < WAVE_NUM_NAMED_MARKERS))
755 							{
756 							TimeType tim = atoi_64(pnt+mlen) * GLOBALS->time_scale;
757 							int slen;
758 							char *sp;
759 
760 							if(tim < LLDescriptor(0)) tim = LLDescriptor(-1);
761 							GLOBALS->named_markers[which_marker] = tim;
762 
763 							while(*pnt) { if(!isspace((int)(unsigned char)*pnt)) pnt++; else break; }
764 							while(*pnt) { if(isspace((int)(unsigned char)*pnt)) pnt++; else break; }
765 
766 							sp = pnt;
767 							slen = strlen(sp);
768 
769 							if(slen)
770 								{
771 								pnt = sp + slen - 1;
772 								do
773 									{
774 									if(isspace((int)(unsigned char)*pnt)) { *pnt = 0; pnt--; slen--; } else { break; }
775 									} while(pnt != (sp-1));
776 								}
777 
778 		                                	if(GLOBALS->marker_names[which_marker]) free_2(GLOBALS->marker_names[which_marker]);
779 		                                	GLOBALS->marker_names[which_marker] = (sp && (*sp) && (tim >= LLDescriptor(0))) ? strdup_2(sp) : NULL;
780 							}
781 						}
782 
783 					continue;
784 					}
785 				else if(*pnt == '$')
786 					{
787 					if(!strncmp(pnt+1, "finish", 6))
788 						{
789 						is_finish = 1;
790 						break;
791 						}
792 					else
793 					if(!strncmp(pnt+1, "next", 4))
794 						{
795 						break;
796 						}
797 					else
798 					if(!strncmp(pnt+1, "name", 4))
799 						{
800 						int slen;
801 						char *sp;
802 
803 						pnt+=5;
804 						while(*pnt) { if(isspace((int)(unsigned char)*pnt)) pnt++; else break; }
805 
806 						sp = pnt;
807 						slen = strlen(sp);
808 
809 						if(slen)
810 							{
811 							pnt = sp + slen - 1;
812 							do
813 								{
814 								if(isspace((int)(unsigned char)*pnt)) { *pnt = 0; pnt--; slen--; } else { break; }
815 								} while(pnt != (sp-1));
816 							}
817 
818 						if(sp && *sp)
819 							{
820 							if(trace_name) free_2(trace_name);
821 							trace_name = strdup_2(sp);
822 							}
823 						}
824 					}
825 				}
826 
827 			vt_curr = vt_curr->next = vt = calloc_2(1, sizeof(struct VectorEnt) + 1);
828 			vt->time = MAX_HISTENT_TIME - 1;
829 			regions++;
830 
831 			/* vt_curr = */ vt_curr->next = vt = calloc_2(1, sizeof(struct VectorEnt) + 1); /* scan-build */
832 			vt->time = MAX_HISTENT_TIME;
833 			regions++;
834 
835 			bv = calloc_2(1, sizeof(struct BitVector) + (sizeof(vptr) * (regions)));
836 			bv->bvname = strdup_2(trace_name ? trace_name : orig_name);
837 			bv->nbits = 1;
838 			bv->numregions = regions;
839 			bv->bits = t->n.vec->bits;
840 
841 			vt = vt_head;
842 			for(i=0;i<regions;i++)
843 				{
844 				bv->vectors[i] = vt;
845 				vt = vt->next;
846 				}
847 
848 			if(!prev_transaction_trace)
849 				{
850 				prev_transaction_trace = bv;
851 				bv->transaction_cache = t->n.vec; /* for possible restore later */
852 				t->n.vec = bv;
853 
854 				t->t_filter_converted = 1;
855 
856 				if(trace_name)	/* if NULL, no need to regen display as trace name didn't change */
857 					{
858 					t->name = t->n.vec->bvname;
859 			               		if(GLOBALS->hier_max_level)
860 			               			t->name = hier_extract(t->name, GLOBALS->hier_max_level);
861 
862 					regen_display();
863 					}
864 				}
865 				else
866 				{
867 				prev_transaction_trace->transaction_chain = bv;
868 				prev_transaction_trace = bv;
869 				}
870 			}
871 		}
872 		else
873 		{
874 		/* failed */
875 		t->flags &= ~(TR_TTRANSLATED|TR_ANALOGMASK);
876 		}
877 	}
878 
879 return(cvt_ok);
880 }
881