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