1 /*
2  * Copyright (c) Tony Bybell 2012-2016.
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 
11 #include "globals.h"
12 #include <config.h>
13 #include "savefile.h"
14 #include "hierpack.h"
15 #ifdef HAVE_SYS_STAT_H
16 #include <sys/stat.h>
17 #endif
18 
19 #ifdef __linux__
20 #ifndef _XOPEN_SOURCE
21 char *strptime(const char *s, const char *format, struct tm *tm);
22 #endif
23 #endif
24 
extract_dumpname_from_save_file(char * lcname,gboolean * modified,int * opt_vcd)25 char *extract_dumpname_from_save_file(char *lcname, gboolean *modified, int *opt_vcd)
26 {
27 char *dfn = NULL;
28 char *sfn = NULL;
29 char *rp = NULL;
30 FILE *f;
31 off_t dumpsiz = -1;
32 time_t dumptim = -1;
33 
34 if ((suffix_check(lcname, ".sav")) || (suffix_check(lcname, ".gtkw")))
35 	{
36 	read_save_helper(lcname, &dfn, &sfn, &dumpsiz, &dumptim, opt_vcd);
37 
38 #if defined __USE_BSD || defined __USE_XOPEN_EXTENDED || defined __CYGWIN__ || defined HAVE_REALPATH || defined __MINGW32__
39 	if(sfn && dfn)
40 		{
41 		char *can = realpath_2(lcname, NULL);
42 		char *fdf = find_dumpfile(sfn, dfn, can);
43 
44 		free(can);
45 		f = fopen(fdf, "rb");
46 		if(f)
47 			{
48 			rp = fdf;
49 			fclose(f);
50 			goto bot;
51 			}
52 		}
53 #endif
54 
55 	if(dfn)
56 		{
57 		f = fopen(dfn, "rb");
58 		if(f)
59 			{
60 			fclose(f);
61 			rp = strdup_2(dfn);
62 			goto bot;
63 			}
64 		}
65 	}
66 
67 bot:
68 if(dfn) free_2(dfn);
69 if(sfn) free_2(sfn);
70 
71 if(modified) *modified = 0;
72 #ifdef HAVE_SYS_STAT_H
73 if(modified && rp && (dumpsiz != -1) && (dumptim != -1))
74 	{
75 	struct stat sbuf;
76         if(!stat(rp, &sbuf))
77 		{
78 		*modified = (dumpsiz != sbuf.st_size) || (dumptim != sbuf.st_mtime);
79                 }
80 	}
81 #endif
82 
83 return(rp);
84 }
85 
86 
append_array_row(nptr n)87 char *append_array_row(nptr n)
88 {
89 int was_packed = HIER_DEPACK_ALLOC;
90 char *hname = hier_decompress_flagged(n->nname, &was_packed);
91 
92 #ifdef WAVE_ARRAY_SUPPORT
93 if(!n->array_height)
94 #endif
95       	{
96 	strcpy(GLOBALS->buf_menu_c_1, hname);
97         }
98 #ifdef WAVE_ARRAY_SUPPORT
99         else
100 	{
101 	sprintf(GLOBALS->buf_menu_c_1, "%s{%d}", hname, n->this_row);
102         }
103 #endif
104 
105 if(was_packed) free_2(hname);
106 
107 return(GLOBALS->buf_menu_c_1);
108 }
109 
110 
write_save_helper(const char * savnam,FILE * wave)111 void write_save_helper(const char *savnam, FILE *wave) {
112 	Trptr t;
113 	int i;
114 	TraceFlagsType def=0;
115 	int sz_x, sz_y;
116 	TimeType prevshift=LLDescriptor(0);
117 	int root_x, root_y;
118         struct strace *st;
119 	int s_ctx_iter;
120 	time_t walltime;
121 
122 	DEBUG(printf("Write Save Fini: %s\n", savnam));
123 
124 	GLOBALS->dumpfile_is_modified = 0; /* writing a save file removes modification */
125 	wave_gtk_window_set_title(GTK_WINDOW(GLOBALS->mainwindow), GLOBALS->winname, GLOBALS->dumpfile_is_modified ? WAVE_SET_TITLE_MODIFIED: WAVE_SET_TITLE_NONE, 0);
126 
127 	time(&walltime);
128 	fprintf(wave, "[*]\n");
129 	fprintf(wave, "[*] "WAVE_VERSION_INFO"\n");
130 	fprintf(wave, "[*] %s",asctime(gmtime(&walltime)));
131 	fprintf(wave, "[*]\n");
132 
133 	if(GLOBALS->loaded_file_name)
134 		{
135 		if((GLOBALS->loaded_file_type == MISSING_FILE)||(GLOBALS->is_optimized_stdin_vcd))
136 			{
137 			/* don't emit dumpfile tag */
138 			}
139 			else
140 			{
141 #ifdef HAVE_SYS_STAT_H
142 			struct stat sbuf;
143 #endif
144 			char *unopt = GLOBALS->unoptimized_vcd_file_name ? GLOBALS->unoptimized_vcd_file_name: GLOBALS->loaded_file_name;
145 #if defined __USE_BSD || defined __USE_XOPEN_EXTENDED || defined __CYGWIN__ || defined HAVE_REALPATH || defined __MINGW32__
146 		        char *can = realpath_2(GLOBALS->optimize_vcd ? unopt : GLOBALS->loaded_file_name, NULL);
147 			const char *cansav = realpath_2(savnam, NULL);
148 			const int do_free = 1;
149 #else
150 			char *can = GLOBALS->optimize_vcd ? unopt : GLOBALS->loaded_file_name;
151 			const char *cansav = savnam;
152 			const int do_free = 0;
153 #endif
154 			fprintf(wave, "[dumpfile] \"%s\"\n", can);
155 #ifdef HAVE_SYS_STAT_H
156 			if(!stat(can, &sbuf))
157 				{
158 				char *asct = asctime(gmtime(&sbuf.st_mtime));
159 				if(asct)
160 					{
161 					char *asct2 = strdup_2(asct);
162 					char *nl = strchr(asct2, '\n');
163 					if(nl) *nl = 0;
164 					fprintf(wave, "[dumpfile_mtime] \"%s\"\n", asct2);
165 					free_2(asct2);
166 					fprintf(wave, "[dumpfile_size] %"PRIu64"\n", sbuf.st_size);
167 					}
168 				}
169 #endif
170 			if(GLOBALS->optimize_vcd && GLOBALS->unoptimized_vcd_file_name) { fprintf(wave, "[optimize_vcd]\n"); }
171 			fprintf(wave, "[savefile] \"%s\"\n", cansav); /* emit also in order to do relative path matching in future... */
172 			if(do_free)
173 				{
174 				free(can);
175 				}
176 			}
177 		}
178 
179 	fprintf(wave, "[timestart] "TTFormat"\n", GLOBALS->tims.start);
180 
181 	get_window_size (&sz_x, &sz_y);
182 	if(!GLOBALS->ignore_savefile_size) fprintf(wave,"[size] %d %d\n", sz_x, sz_y);
183 
184 	get_window_xypos(&root_x, &root_y);
185 
186 	if(!GLOBALS->ignore_savefile_pos) fprintf(wave,"[pos] %d %d\n", root_x + GLOBALS->xpos_delta, root_y + GLOBALS->ypos_delta);
187 
188 	fprintf(wave,"*%f "TTFormat, (float)(GLOBALS->tims.zoom),GLOBALS->tims.marker);
189 
190 	for(i=0;i<WAVE_NUM_NAMED_MARKERS;i++)
191 		{
192 		TimeType nm = GLOBALS->named_markers[i]; /* gcc compiler problem...thinks this is a 'long int' in printf format warning reporting */
193 		fprintf(wave," "TTFormat,nm);
194 		}
195 	fprintf(wave,"\n");
196 
197 	for(i=0;i<WAVE_NUM_NAMED_MARKERS;i++)
198 		{
199 		if(GLOBALS->marker_names[i])
200 			{
201 			char mbuf[16];
202 
203 			make_bijective_marker_id_string(mbuf, i);
204 			if(strlen(mbuf)<2)
205 				{
206 				fprintf(wave, "[markername] %s%s\n", mbuf, GLOBALS->marker_names[i]);
207 				}
208 				else
209 				{
210 				fprintf(wave, "[markername_long] %s %s\n", mbuf, GLOBALS->marker_names[i]);
211 				}
212 			}
213 		}
214 
215 	if(GLOBALS->ruler_step)
216 		{
217 		fprintf(wave, "[ruler] "TTFormat" "TTFormat"\n", GLOBALS->ruler_origin, GLOBALS->ruler_step);
218 		}
219 
220 #if WAVE_USE_GTK2
221 	if(GLOBALS->open_tree_nodes)
222 		{
223 		dump_open_tree_nodes(wave, GLOBALS->open_tree_nodes);
224 		}
225 #endif
226 
227 #if GTK_CHECK_VERSION(2,4,0)
228 	if(!GLOBALS->ignore_savefile_pane_pos)
229 		{
230 		if(GLOBALS->toppanedwindow)
231 			{
232 			fprintf(wave, "[sst_width] %d\n", gtk_paned_get_position(GTK_PANED(GLOBALS->toppanedwindow)));
233 			}
234 		if(GLOBALS->panedwindow)
235 			{
236 			fprintf(wave, "[signals_width] %d\n", gtk_paned_get_position(GTK_PANED(GLOBALS->panedwindow)));
237 			}
238 		if(GLOBALS->expanderwindow)
239 	        	{
240 			GLOBALS->sst_expanded = gtk_expander_get_expanded(GTK_EXPANDER(GLOBALS->expanderwindow));
241 			fprintf(wave, "[sst_expanded] %d\n", GLOBALS->sst_expanded);
242 			}
243 		if(GLOBALS->sst_vpaned)
244 			{
245 			fprintf(wave, "[sst_vpaned_height] %d\n", gtk_paned_get_position(GTK_PANED(GLOBALS->sst_vpaned)));
246 			}
247 		}
248 #endif
249 
250 	t=GLOBALS->traces.first;
251 	while(t)
252 		{
253 		if((t->flags!=def)||(t==GLOBALS->traces.first))
254 			{
255 			if((t->flags & TR_PTRANSLATED) && (!t->p_filter)) t->flags &= (~TR_PTRANSLATED);
256 			if((t->flags & TR_FTRANSLATED) && (!t->f_filter)) t->flags &= (~TR_FTRANSLATED);
257 			if((t->flags & TR_TTRANSLATED) && (!t->t_filter)) t->flags &= (~TR_TTRANSLATED);
258 			fprintf(wave,"@%"TRACEFLAGSPRIFMT"\n",def=t->flags);
259 			}
260 
261 		if((t->shift)||((prevshift)&&(!t->shift)))
262 			{
263 			fprintf(wave,">"TTFormat"\n", t->shift);
264 			}
265 		prevshift=t->shift;
266 
267 		if(!(t->flags&(TR_BLANK|TR_ANALOG_BLANK_STRETCH)))
268 			{
269 			if(t->t_color)
270 				{
271 				fprintf(wave, "[color] %d\n", t->t_color);
272 				}
273 			if(t->flags & TR_FPDECSHIFT)
274 				{
275 				fprintf(wave, "[fpshift_count] %d\n", t->t_fpdecshift);
276 				}
277 
278 			if(t->flags & TR_FTRANSLATED)
279 				{
280 				if(t->f_filter && GLOBALS->filesel_filter[t->f_filter])
281 					{
282 #if defined __USE_BSD || defined __USE_XOPEN_EXTENDED || defined __CYGWIN__ || defined HAVE_REALPATH || defined __MINGW32__
283 			                char *can = realpath_2(GLOBALS->filesel_filter[t->f_filter], NULL);
284 					fprintf(wave, "^%d %s\n", t->f_filter, can);
285 					free(can);
286 #else
287 					fprintf(wave, "^%d %s\n", t->f_filter, GLOBALS->filesel_filter[t->f_filter]);
288 #endif
289 					}
290 					else
291 					{
292 					fprintf(wave, "^%d %s\n", 0, "disabled");
293 					}
294 				}
295 			else
296 			if(t->flags & TR_PTRANSLATED)
297 				{
298 				if(t->p_filter && GLOBALS->procsel_filter[t->p_filter])
299 					{
300 #if defined __USE_BSD || defined __USE_XOPEN_EXTENDED || defined __CYGWIN__ || defined HAVE_REALPATH || defined __MINGW32__
301 			                char *can = realpath_2(GLOBALS->procsel_filter[t->p_filter], NULL);
302 					fprintf(wave, "^>%d %s\n", t->p_filter, can);
303 					free(can);
304 #else
305 					fprintf(wave, "^>%d %s\n", t->p_filter, GLOBALS->procsel_filter[t->p_filter]);
306 #endif
307 					}
308 					else
309 					{
310 					fprintf(wave, "^>%d %s\n", 0, "disabled");
311 					}
312 				}
313 
314 			/* NOT an else! */
315 			if(t->flags & TR_TTRANSLATED)
316 				{
317 				if(t->transaction_args)
318 					{
319 					fprintf(wave, "[transaction_args] \"%s\"\n", t->transaction_args);
320 					}
321 					else
322 					{
323 					fprintf(wave, "[transaction_args] \"%s\"\n", "");
324 					}
325 
326 				if(t->t_filter && GLOBALS->ttranssel_filter[t->t_filter])
327 					{
328 #if defined __USE_BSD || defined __USE_XOPEN_EXTENDED || defined __CYGWIN__ || defined HAVE_REALPATH || defined __MINGW32__
329 			                char *can = realpath_2(GLOBALS->ttranssel_filter[t->t_filter], NULL);
330 					fprintf(wave, "^<%d %s\n", t->t_filter, can);
331 					free(can);
332 #else
333 					fprintf(wave, "^<%d %s\n", t->t_filter, GLOBALS->ttranssel_filter[t->t_filter]);
334 #endif
335 					}
336 					else
337 					{
338 					fprintf(wave, "^<%d %s\n", 0, "disabled");
339 					}
340 				}
341 
342 			if(t->vector && !(t->n.vec->transaction_cache && t->n.vec->transaction_cache->transaction_nd))
343 				{
344 				int ix;
345 				nptr *nodes;
346 				bptr bits;
347 				baptr ba;
348 
349 				if (HasAlias(t)) { fprintf(wave,"+{%s} ", t->name_full); }
350 				bits = t->n.vec->bits;
351 				ba = bits ? bits->attribs : NULL;
352 
353 				fprintf(wave,"%c{%s}", ba ? ':' : '#',
354 						t->n.vec->transaction_cache ? t->n.vec->transaction_cache->bvname : t->n.vec->bvname);
355 
356 				nodes=t->n.vec->bits->nodes;
357 				for(ix=0;ix<t->n.vec->bits->nnbits;ix++)
358 					{
359 					if(nodes[ix]->expansion)
360 						{
361 						fprintf(wave," (%d)%s",nodes[ix]->expansion->parentbit, append_array_row(nodes[ix]->expansion->parent));
362 						}
363 						else
364 						{
365 						fprintf(wave," %s",append_array_row(nodes[ix]));
366 						}
367 					if(ba)
368 						{
369 						fprintf(wave, " "TTFormat" %"TRACEFLAGSPRIFMT, ba[ix].shift, ba[ix].flags);
370 						}
371 					}
372 				fprintf(wave,"\n");
373 				}
374 				else
375 				{
376 				nptr nd = (t->vector && t->n.vec->transaction_cache && t->n.vec->transaction_cache->transaction_nd) ?
377 						t->n.vec->transaction_cache->transaction_nd : t->n.nd;
378 
379 				if(HasAlias(t))
380 					{
381 					if(nd->expansion)
382 						{
383 						fprintf(wave,"+{%s} (%d)%s\n",t->name_full,nd->expansion->parentbit, append_array_row(nd->expansion->parent));
384 						}
385 						else
386 						{
387 						fprintf(wave,"+{%s} %s\n",t->name_full,append_array_row(nd));
388 						}
389 					}
390 					else
391 					{
392 					if(nd->expansion)
393 						{
394 						fprintf(wave,"(%d)%s\n",nd->expansion->parentbit, append_array_row(nd->expansion->parent));
395 						}
396 						else
397 						{
398 						fprintf(wave,"%s\n",append_array_row(nd));
399 						}
400 					}
401 				}
402 			}
403 			else
404 			{
405 			if(!t->name) fprintf(wave,"-\n");
406 			else fprintf(wave,"-%s\n",t->name);
407 			}
408 		t=t->t_next;
409 		}
410 
411 	WAVE_STRACE_ITERATOR(s_ctx_iter)
412 	{
413 	GLOBALS->strace_ctx = &GLOBALS->strace_windows[GLOBALS->strace_current_window = s_ctx_iter];
414 	fprintf(wave, "[pattern_trace] %d\n", s_ctx_iter);
415 
416 	if(GLOBALS->strace_ctx->timearray)
417 		{
418 		if(GLOBALS->strace_ctx->shadow_straces)
419 			{
420 			swap_strace_contexts();
421 
422 			st=GLOBALS->strace_ctx->straces;
423 			if(GLOBALS->strace_ctx->straces)
424 				{
425 				fprintf(wave, "!%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);
426 				}
427 
428 			while(st)
429 				{
430 				if(st->value==ST_STRING)
431 					{
432 					fprintf(wave, "?\"%s\n", st->string ? st->string : ""); /* search type for this trace is string.. */
433 					}
434 					else
435 					{
436 					fprintf(wave, "?%02x\n", (unsigned char)st->value);	/* else search type for this trace.. */
437 					}
438 
439 				t=st->trace;
440 
441 				if(t->flags!=def)
442 					{
443 					if((t->flags & TR_FTRANSLATED) && (!t->f_filter)) t->flags &= (~TR_FTRANSLATED);
444 					if((t->flags & TR_PTRANSLATED) && (!t->p_filter)) t->flags &= (~TR_PTRANSLATED);
445 					if((t->flags & TR_TTRANSLATED) && (!t->t_filter)) t->flags &= (~TR_TTRANSLATED);
446 					fprintf(wave,"@%"TRACEFLAGSPRIFMT"\n",def=t->flags);
447 					}
448 
449 				if((t->shift)||((prevshift)&&(!t->shift)))
450 					{
451 					fprintf(wave,">"TTFormat"\n", t->shift);
452 					}
453 				prevshift=t->shift;
454 
455 				if(!(t->flags&(TR_BLANK|TR_ANALOG_BLANK_STRETCH)))
456 					{
457 					if(t->flags & TR_FTRANSLATED)
458 						{
459 						if(t->f_filter && GLOBALS->filesel_filter[t->f_filter])
460 							{
461 							fprintf(wave, "^%d %s\n", t->f_filter, GLOBALS->filesel_filter[t->f_filter]);
462 							}
463 							else
464 							{
465 							fprintf(wave, "^%d %s\n", 0, "disabled");
466 							}
467 						}
468 					else
469 					if(t->flags & TR_PTRANSLATED)
470 						{
471 						if(t->p_filter && GLOBALS->procsel_filter[t->p_filter])
472 							{
473 							fprintf(wave, "^>%d %s\n", t->p_filter, GLOBALS->procsel_filter[t->p_filter]);
474 							}
475 							else
476 							{
477 							fprintf(wave, "^>%d %s\n", 0, "disabled");
478 							}
479 						}
480 
481 					/* NOT an else! */
482 					if(t->flags & TR_TTRANSLATED)
483 						{
484 						if(t->transaction_args)
485 							{
486 							fprintf(wave, "[transaction_args] \"%s\"\n", t->transaction_args);
487 							}
488 							else
489 							{
490 							fprintf(wave, "[transaction_args] \"%s\"\n", "");
491 							}
492 
493 						if(t->t_filter && GLOBALS->ttranssel_filter[t->t_filter])
494 							{
495 #if defined __USE_BSD || defined __USE_XOPEN_EXTENDED || defined __CYGWIN__ || defined HAVE_REALPATH || defined __MINGW32__
496 					                char *can = realpath_2(GLOBALS->ttranssel_filter[t->t_filter], NULL);
497 							fprintf(wave, "^<%d %s\n", t->t_filter, can);
498 							free(can);
499 #else
500 							fprintf(wave, "^<%d %s\n", t->t_filter, GLOBALS->ttranssel_filter[t->t_filter]);
501 #endif
502 							}
503 							else
504 							{
505 							fprintf(wave, "^<%d %s\n", 0, "disabled");
506 							}
507 						}
508 
509 
510 				if(t->vector && !(t->n.vec->transaction_cache && t->n.vec->transaction_cache->transaction_nd))
511 						{
512 						int ix;
513                                                 nptr *nodes;
514 						bptr bits;
515 						baptr ba;
516 
517 						if (HasAlias(t)) { fprintf(wave,"+{%s} ", t->name_full); }
518 
519 						bits = t->n.vec->bits;
520 						ba = bits ? bits->attribs : NULL;
521 
522 						fprintf(wave,"%c{%s}", ba ? ':' : '#',
523 							t->n.vec->transaction_cache ? t->n.vec->transaction_cache->bvname : t->n.vec->bvname);
524 
525 						nodes=t->n.vec->bits->nodes;
526 						for(ix=0;ix<t->n.vec->bits->nnbits;ix++)
527 							{
528 							if(nodes[ix]->expansion)
529 								{
530 								fprintf(wave," (%d)%s",nodes[ix]->expansion->parentbit, append_array_row(nodes[ix]->expansion->parent));
531 								}
532 								else
533 								{
534 								fprintf(wave," %s",append_array_row(nodes[ix]));
535 								}
536 							if(ba)
537 								{
538 								fprintf(wave, " "TTFormat" %"TRACEFLAGSPRIFMT, ba[ix].shift, ba[ix].flags);
539 								}
540 							}
541 						fprintf(wave,"\n");
542 						}
543 						else
544 						{
545 						nptr nd = (t->vector && t->n.vec->transaction_cache && t->n.vec->transaction_cache->transaction_nd) ?
546 								t->n.vec->transaction_cache->transaction_nd : t->n.nd;
547 
548 						if(HasAlias(t))
549 							{
550 							if(nd->expansion)
551 								{
552 								fprintf(wave,"+{%s} (%d)%s\n",t->name_full,nd->expansion->parentbit, append_array_row(nd->expansion->parent));
553 								}
554 								else
555 								{
556 								fprintf(wave,"+{%s} %s\n",t->name_full,append_array_row(nd));
557 								}
558 							}
559 							else
560 							{
561 							if(nd->expansion)
562 								{
563 								fprintf(wave,"(%d)%s\n",nd->expansion->parentbit, append_array_row(nd->expansion->parent));
564 								}
565 								else
566 								{
567 								fprintf(wave,"%s\n",append_array_row(nd));
568 								}
569 							}
570 						}
571 					}
572 
573 				st=st->next;
574 				} /* while(st)... */
575 
576 			if(GLOBALS->strace_ctx->straces)
577 				{
578 				fprintf(wave, "!!\n");	/* mark end of strace region */
579 				}
580 
581 				swap_strace_contexts();
582 			}
583 			else
584 			{
585 			struct mprintf_buff_t *mt = GLOBALS->strace_ctx->mprintf_buff_head;
586 
587 			while(mt)
588 				{
589 				fprintf(wave, "%s", mt->str);
590 				mt=mt->next;
591 				}
592 			}
593 
594 		} /* if(timearray)... */
595 	}
596 }
597 
598 
read_save_helper_relative_init(char * wname)599 void read_save_helper_relative_init(char *wname)
600 {
601 /* for relative files in parsewavline() */
602 if(GLOBALS->lcname)
603 	{
604         free_2(GLOBALS->lcname);
605         }
606 
607 GLOBALS->lcname = wname ? strdup_2(wname) : NULL;
608 
609 if(GLOBALS->sfn)
610 	{
611         free_2(GLOBALS->sfn);
612         GLOBALS->sfn = NULL;
613         }
614 }
615 
616 
get_relative_adjusted_name(char * sfn,char * dfn,char * lcname)617 char *get_relative_adjusted_name(char *sfn, char *dfn, char *lcname)
618 {
619 char *rp = NULL;
620 FILE *f;
621 
622 #if defined __USE_BSD || defined __USE_XOPEN_EXTENDED || defined __CYGWIN__ || defined HAVE_REALPATH
623         if(sfn && dfn)
624                 {
625                 char *can = realpath_2(lcname, NULL);
626                 char *fdf = find_dumpfile(sfn, dfn, can);
627 
628                 free(can);
629 
630 		if(fdf)
631 			{
632 	                f = fopen(fdf, "rb");
633 	                if(f)
634 	                        {
635 	                        rp = fdf;
636 	                        fclose(f);
637 	                        goto bot;
638 	                        }
639 			}
640                 }
641 #endif
642 
643         if(dfn)
644                 {
645                 f = fopen(dfn, "rb");
646                 if(f)
647                         {
648                         fclose(f);
649                         rp = strdup_2(dfn);
650                         goto bot;
651                         }
652                 }
653 
654 bot:
655 return(rp);
656 }
657 
658 
read_save_helper(char * wname,char ** dumpfile,char ** savefile,off_t * dumpsiz,time_t * dumptim,int * opt_vcd)659 int read_save_helper(char *wname, char **dumpfile, char **savefile, off_t *dumpsiz, time_t *dumptim, int *opt_vcd) {
660         FILE *wave;
661         char *str = NULL;
662         int wave_is_compressed;
663 	char traces_already_exist = (GLOBALS->traces.first != NULL);
664 	int rc = -1;
665 	int extract_dumpfile_savefile_only = (dumpfile != NULL) && (savefile != NULL);
666 
667 	GLOBALS->is_gtkw_save_file = suffix_check(wname, ".gtkw") || suffix_check(wname, ".gtkw.gz") || suffix_check(wname, ".gtkw.zip");
668 
669 	if(suffix_check(wname, ".gz") || suffix_check(wname, ".zip"))
670                 {
671                 str=wave_alloca(strlen(wname)+5+1);
672                 strcpy(str,"zcat ");
673                 strcpy(str+5,wname);
674                 wave=popen(str,"r");
675                 wave_is_compressed=~0;
676                 }
677                 else
678                 {
679                 wave=fopen(wname,"rb");
680                 wave_is_compressed=0;
681                 }
682 
683 
684         if(!wave)
685                 {
686                 fprintf(stderr, "Error opening save file '%s' for reading.\n", wname);
687 		perror("Why");
688 		errno=0;
689                 }
690                 else
691                 {
692                 char *iline;
693 		int s_ctx_iter;
694 
695 		if(extract_dumpfile_savefile_only)
696 			{
697 	                while((iline=fgetmalloc(wave)))
698 	                        {
699 				if(!strncmp(iline,  "[dumpfile]", 10))
700 					{
701 					char *lhq = strchr(iline+10, '"');
702 					char *rhq = strrchr(iline+10, '"');
703 					if((lhq) && (rhq) && (lhq != rhq)) /* no real need to check rhq != NULL*/
704 						{
705 						*rhq = 0;
706 						if(*dumpfile) free_2(*dumpfile);
707 						*dumpfile = strdup_2(lhq + 1);
708 						}
709 					}
710 				else
711 				if(!strncmp(iline,  "[dumpfile_mtime]", 16))
712 					{
713 					if(dumptim)
714 						{
715 						struct tm tm;
716 						time_t t;
717 						char *lhq = strchr(iline+16, '"');
718 						char *rhq = strrchr(iline+16, '"');
719 						memset(&tm, 0, sizeof(struct tm));
720 
721 						*dumptim = -1;
722 #if !defined _MSC_VER && !defined __MINGW32__
723 						/* format is: "Fri Feb  4 15:50:48 2011" */
724 						if(lhq && rhq && (lhq != rhq))
725 							{
726 							int slen;
727 							char *strp_buf;
728 
729 							*rhq = 0;
730 							slen = strlen(lhq+1);
731 							strp_buf = calloc_2(1, slen + 32); /* workaround: linux strptime seems to overshoot its buffer */
732 							strcpy(strp_buf, lhq+1);
733 
734 							if(strptime(strp_buf, "%a %b %d %H:%M:%S %Y", &tm) != NULL)
735 								{
736 								t = timegm(&tm);
737 								if(t != -1)
738 									{
739 									*dumptim = t;
740 									}
741 								}
742 
743 							free_2(strp_buf);
744 							}
745 #endif
746 						}
747 					}
748 				else
749 				if(!strncmp(iline,  "[dumpfile_size]", 15))
750 					{
751 					if(dumpsiz)
752 						{
753 						*dumpsiz = atoi_64(iline+15);
754 						}
755 					}
756 				else
757 				if(!strncmp(iline,  "[savefile]", 10))
758 					{
759 					char *lhq = strchr(iline+10, '"');
760 					char *rhq = strrchr(iline+10, '"');
761 					if((lhq) && (rhq) && (lhq != rhq)) /* no real need to check rhq != NULL*/
762 						{
763 						*rhq = 0;
764 						if(*savefile) free_2(*savefile);
765 						*savefile = strdup_2(lhq + 1);
766 						}
767 					}
768 				else
769 				if(!strncmp(iline,  "[optimize_vcd]", 14))
770 					{
771 					if(opt_vcd) { *opt_vcd = 1; }
772 					}
773 
774 	                        free_2(iline);
775 				rc++;
776 	                        }
777 
778 	                if(wave_is_compressed) pclose(wave); else fclose(wave);
779 			return(rc);
780 			}
781 
782 
783 		read_save_helper_relative_init(wname);
784 
785 
786                 WAVE_STRACE_ITERATOR(s_ctx_iter)
787                         {
788                         GLOBALS->strace_ctx = &GLOBALS->strace_windows[GLOBALS->strace_current_window = s_ctx_iter];
789                         GLOBALS->strace_ctx->shadow_encountered_parsewavline = 0;
790                         }
791 
792 		if(GLOBALS->traces.total)
793 			{
794 			  GLOBALS->group_depth=0;
795 			  /*		 AddBlankTrace(NULL); in order to terminate any possible collapsed groups */
796 			}
797 
798 		if(GLOBALS->is_lx2)
799 			{
800 	                while((iline=fgetmalloc(wave)))
801 	                        {
802 	                        parsewavline_lx2(iline, NULL, 0);
803 	                        free_2(iline);
804 	                        }
805 
806 			lx2_import_masked();
807 
808 			if(wave_is_compressed)
809 		                {
810 				pclose(wave);
811 		                wave=popen(str,"r");
812 		                }
813 		                else
814 		                {
815 				fclose(wave);
816 		                wave=fopen(wname,"rb");
817 		                }
818 
819 		        if(!wave)
820 		                {
821 		                fprintf(stderr, "Error opening save file '%s' for reading.\n", wname);
822 				perror("Why");
823 				errno=0;
824 				return(rc);
825 		                }
826 			}
827 
828                 GLOBALS->default_flags=TR_RJUSTIFY;
829                 GLOBALS->default_fpshift=0;
830 		GLOBALS->shift_timebase_default_for_add=LLDescriptor(0);
831 		GLOBALS->strace_current_window = 0; /* in case there are shadow traces */
832 
833 		rc = 0;
834 		GLOBALS->which_t_color = 0;
835                 while((iline=fgetmalloc(wave)))
836                         {
837                         parsewavline(iline, NULL, 0);
838 			GLOBALS->strace_ctx->shadow_encountered_parsewavline |= GLOBALS->strace_ctx->shadow_active;
839                         free_2(iline);
840 			rc++;
841                         }
842 		GLOBALS->which_t_color = 0;
843 
844 		WAVE_STRACE_ITERATOR(s_ctx_iter)
845 			{
846 			GLOBALS->strace_ctx = &GLOBALS->strace_windows[GLOBALS->strace_current_window = s_ctx_iter];
847 
848 			if(GLOBALS->strace_ctx->shadow_encountered_parsewavline)
849 				{
850 				GLOBALS->strace_ctx->shadow_encountered_parsewavline = 0;
851 
852 				if(GLOBALS->strace_ctx->shadow_straces)
853 					{
854 					GLOBALS->strace_ctx->shadow_active = 1;
855 
856 					swap_strace_contexts();
857 					strace_maketimetrace(1);
858 					swap_strace_contexts();
859 
860 					GLOBALS->strace_ctx->shadow_active = 0;
861 					}
862 				}
863 			}
864 
865                 GLOBALS->default_flags=TR_RJUSTIFY;
866                 GLOBALS->default_fpshift=0;
867 		GLOBALS->shift_timebase_default_for_add=LLDescriptor(0);
868 		update_markertime(GLOBALS->tims.marker);
869                 if(wave_is_compressed) pclose(wave); else fclose(wave);
870 
871 		if(traces_already_exist) GLOBALS->timestart_from_savefile_valid = 0;
872 
873 		EnsureGroupsMatch();
874 
875 		GLOBALS->signalwindow_width_dirty=1;
876 		MaxSignalLength();
877 		signalarea_configure_event(GLOBALS->signalarea, NULL);
878 		wavearea_configure_event(GLOBALS->wavearea, NULL);
879 
880 #ifdef MAC_INTEGRATION
881 		if(GLOBALS->num_notebook_pages > 1)
882 #endif
883 			{
884 			if(!GLOBALS->block_xy_update)
885 				{
886 				int x, y;
887 
888 				get_window_size(&x, &y);
889 				set_window_size(x, y);
890 				}
891 			}
892                 }
893 
894 	GLOBALS->current_translate_file = 0;
895 
896 return(rc);
897 }
898 
899 /******************************************************************/
900 
901 /*
902  * attempt to synthesize bitwise on loader fail...caller must free return pnt
903  */
synth_blastvec(char * w)904 static char *synth_blastvec(char *w)
905 {
906 char *mem = NULL;
907 char *t;
908 char *lbrack, *colon, *rbrack, *rname, *msbs, *lsbs;
909 int wlen, bitlen, msb, lsb;
910 int msbslen, lsbslen, maxnumlen;
911 int i, siz;
912 
913 if(w)
914 	{
915 	if((lbrack = strrchr(w, '[')))
916 	if((colon = strchr(lbrack+1, ':')))
917 	if((rbrack = strchr(colon+1, ']')))
918 		{
919 		*lbrack = *colon = *rbrack = 0;
920 		msbs = lbrack + 1;
921 		lsbs = colon + 1;
922 		rname = hier_extract(w, GLOBALS->hier_max_level);
923 
924 		msb = atoi(msbs);
925 		lsb = atoi(lsbs);
926 		bitlen = (msb > lsb) ? (msb - lsb + 1) : (lsb - msb + 1);
927 		if(bitlen > 1)
928 			{
929 			wlen = strlen(w);
930 
931 			msbslen = strlen(msbs);
932 			lsbslen = strlen(lsbs);
933 			maxnumlen = (msbslen > lsbslen) ? msbslen : lsbslen;
934 
935 			siz = 	1 + 				/* # */
936 				strlen(rname) +			/* vector alias name */
937 				1+				/*   */
938 				1+				/* [ */
939 				msbslen+			/* msb */
940 				1+				/* : */
941 				lsbslen+			/* lsb */
942 				1+				/* ] */
943 				1;				/*   */
944 
945 			siz +=  bitlen * (
946 				wlen +				/* full bitname */
947 				1+				/* [ */
948 				maxnumlen+			/* individual bit */
949 				1+				/* ] */
950 				1				/*   */
951 				);
952 
953 			mem = calloc_2(1, siz);
954 			t = mem + sprintf(mem, "#%s[%d:%d] ", rname, msb, lsb);
955 
956 			if(msb > lsb)
957 				{
958 				for(i = msb; i >= lsb; i--)
959 					{
960 					t += sprintf(t, "%s[%d]", w, i);
961 					if(i!=lsb) t += sprintf(t, " ");
962 					}
963 				}
964 				else
965 				{
966 				for(i = msb; i <= lsb; i++)
967 					{
968 					t += sprintf(t, "%s[%d]", w, i);
969 					if(i!=lsb) t += sprintf(t, " ");
970 					}
971 				}
972 
973 			/* fprintf(stderr, "%d,%d: %s\n", siz, strlen(mem), mem); */
974 			}
975 
976 		}
977 	}
978 
979 return(mem);
980 }
981 
982 /******************************************************************/
983 
984 /*
985  * Parse a line of the wave file and act accordingly..
986  * Returns nonzero if trace(s) added.
987  */
parsewavline(char * w,char * alias,int depth)988 int parsewavline(char *w, char *alias, int depth)
989 {
990   int i;
991   int len;
992   char *w2;
993   nptr nexp;
994   unsigned int rows = 0;
995   char *prefix, *suffix, *new;
996   char *prefix_init, *w2_init;
997   unsigned int mode;
998   int current_grp_depth = -1;
999 
1000   if(!(len=strlen(w))) return(0);
1001   if(*(w+len-1)=='\n')
1002     {
1003       *(w+len-1)=0x00; /* strip newline if present */
1004       len--;
1005       if(!len) return(0);
1006     }
1007 
1008   while(1)
1009     {
1010       if(isspace((int)(unsigned char)*w)) { w++; continue; }
1011       if(!(*w)) return(0);	/* no args */
1012       break;			/* start grabbing chars from here */
1013     }
1014 
1015   w2=w;
1016 
1017   /* sscanf(w2,"%s",prefix); */
1018 
1019  prefix=(char *)wave_alloca(len+1);
1020  suffix=(char *)wave_alloca(len+1);
1021  new=(char *)wave_alloca(len+1);
1022  memset(new, 0, len+1); /* scan-build */
1023 
1024  prefix_init = prefix;
1025  w2_init = new;
1026  mode = 0; /* 0 = before "{", 1 = after "{", 2 = after "}" or " " */
1027 
1028  while(*w2)
1029    {
1030      if((mode == 0) && (*w2 == '{'))
1031        {
1032 	 mode = 1;
1033 	 w2++;
1034        }
1035      else if((mode == 1) && (*w2 == '}'))
1036        {
1037 	 /* strcpy(prefix, ""); */
1038 	 *(prefix) = '\0';
1039 	 mode = 2;
1040 	 w2++;
1041        }
1042      else if((mode == 0) && (*w2 == ' '))
1043        {
1044 	 /* strcpy(prefix, ""); */
1045 	 *(prefix) = '\0';
1046 	 strcpy(new, w2);
1047 	 mode = 2;
1048 	 w2++;
1049 	 new++;
1050        }
1051      else
1052        {
1053 	 strcpy(new, w2);
1054 	 if (mode != 2)
1055 	   {
1056 	     strcpy(prefix, w2);
1057 	     prefix++;
1058 	   }
1059 	 w2++;
1060 	 new++;
1061        }
1062    }
1063 
1064  prefix = prefix_init;
1065  w2 = w2_init;
1066 
1067  /* printf("HHHHH |%s| %s\n", prefix, w2); */
1068 
1069 
1070 if(*w2=='*')
1071 	{
1072 	float f;
1073 	TimeType ttlocal;
1074 	int which=0;
1075 
1076 	GLOBALS->zoom_was_explicitly_set=~0;
1077 	w2++;
1078 
1079 	for(;;)
1080 		{
1081 		while(*w2==' ') w2++;
1082 		if(*w2==0) return(~0);
1083 
1084 		if(!which)
1085 			{
1086 			sscanf(w2,"%f",&f);
1087 			if((!GLOBALS->do_initial_zoom_fit)||(!GLOBALS->do_initial_zoom_fit_used))
1088 				{
1089 				GLOBALS->tims.zoom=(gdouble)f;
1090 				}
1091 			}
1092 		else
1093 		{
1094 		sscanf(w2,TTFormat,&ttlocal);
1095 		switch(which)
1096 			{
1097 			case 1:  GLOBALS->tims.marker=ttlocal; break;
1098 			default:
1099 				if((which-2)<WAVE_NUM_NAMED_MARKERS) GLOBALS->named_markers[which-2]=ttlocal;
1100 				break;
1101 			}
1102 		}
1103 		which++;
1104 		w2++;
1105 		for(;;)
1106 			{
1107 			if(*w2==0) return(~0);
1108 			if(*w2=='\n') return(~0);
1109 			if(*w2!=' ') w2++; else break;
1110 			}
1111 		}
1112 	}
1113 else
1114 if(*w2=='-')
1115 	{
1116 	AddBlankTrace((*(w2+1)!=0)?(w2+1):NULL);
1117 	}
1118 else
1119 if(*w2=='>')
1120 	{
1121 	char *wnptr=(*(w2+1)!=0)?(w2+1):NULL;
1122 	GLOBALS->shift_timebase_default_for_add=wnptr?atoi_64(wnptr):LLDescriptor(0);
1123 	}
1124 else
1125 if(*w2=='@')
1126 	{
1127 	/* handle trace flags */
1128 	sscanf(w2+1, "%"TRACEFLAGSSCNFMT, &GLOBALS->default_flags);
1129 	if( (GLOBALS->default_flags & (TR_FTRANSLATED|TR_PTRANSLATED)) == (TR_FTRANSLATED|TR_PTRANSLATED) )
1130 		{
1131 		GLOBALS->default_flags &= ~TR_PTRANSLATED; /* safest bet though this is a cfg file error */
1132 		}
1133 
1134 	return(~0);
1135 	}
1136 else
1137 if(*w2=='+')
1138 	{
1139 	/* handle aliasing */
1140 	  struct symbol *s;
1141 	  sscanf(w2+strlen(prefix),"%s",suffix);
1142 
1143 	  if(suffix[0]=='(')
1144 	    {
1145 	      for(i=1;;i++)
1146 		{
1147 		  if(suffix[i]==0) return(0);
1148 		  if((suffix[i]==')')&&(suffix[i+1])) {i++; break; }
1149 		}
1150 
1151 	      s=symfind(suffix+i, &rows);
1152 	      if (s) {
1153 		nexp = ExtractNodeSingleBit(&s->n[rows], atoi(suffix+1));
1154 		if(nexp)
1155 		  {
1156 		    AddNode(nexp, prefix+1);
1157 		    return(~0);
1158 		  }
1159 		else
1160 		  {
1161 		    return(0);
1162 		  }
1163 	      }
1164 	      else
1165 		{
1166 		char *lp = strrchr(suffix+i, '[');
1167 		if(lp)
1168 			{
1169 			char *ns = malloc_2(strlen(suffix+i) + 32);
1170 			char *colon = strchr(lp+1, ':');
1171 			int msi, lsi, bval, actual;
1172 			*lp = 0;
1173 
1174 			bval = atoi(suffix+1);
1175 			if(colon)
1176 				{
1177 				msi = atoi(lp+1);
1178 				lsi = atoi(colon+1);
1179 
1180 				if(lsi > msi)
1181 					{
1182 					actual = msi + bval;
1183 					}
1184 					else
1185 					{
1186 					actual = msi - bval;
1187 					}
1188 				}
1189 				else
1190 				{
1191 				actual = bval; /* punt */
1192 				}
1193 
1194 			sprintf(ns, "%s[%d]", suffix+i, actual);
1195 			*lp = '[';
1196 
1197 			s=symfind(ns, &rows);
1198 			free_2(ns);
1199 			if(s)
1200 				{
1201 				AddNode(&s->n[rows], prefix+1);
1202 				return(~0);
1203 				}
1204 
1205 			}
1206 
1207 		  return(0);
1208 		}
1209 	    }
1210 	  else
1211 	    {
1212 	      int rc;
1213 
1214 	      char *newl   = strdup_2(w2+strlen(prefix));
1215 	      char *nalias = strdup_2(prefix+1);
1216 
1217 	      rc = parsewavline(newl, nalias, depth);
1218 	      if (newl)   free_2(newl);
1219 	      if (nalias) free_2(nalias);
1220 
1221 	      return rc;
1222 	    }
1223 	/* 	{ */
1224 /* 		if((s=symfind(suffix, &rows))) */
1225 /* 			{ */
1226 /* 			AddNode(&s->n[rows],prefix+1); */
1227 /* 			return(~0); */
1228 /* 			} */
1229 /* 			else */
1230 /* 			{ */
1231 /* 			return(0); */
1232 /* 			} */
1233 /* 		} */
1234 	}
1235 else
1236 if((*w2=='#')||(*w2==':'))
1237 	{
1238 	/* handle bitvec */
1239 	bvptr v=NULL;
1240 	bptr b=NULL;
1241 	int maketyp = (*w2=='#');
1242 
1243 	w2=w2+strlen(prefix);
1244 	while(1)
1245 		{
1246 		if(isspace((int)(unsigned char)*w2)) { w2++; continue; }
1247 		if(!(*w2)) return(0);	/* no more args */
1248 		break;			/* start grabbing chars from here */
1249 		}
1250 
1251 	b = maketyp ? makevec(prefix+1,w2) : makevec_annotated(prefix+1,w2);	/* '#' vs ':' cases... */
1252 
1253 	if(GLOBALS->default_flags&TR_GRP_BEGIN) { current_grp_depth = GLOBALS->group_depth; }
1254 
1255 	if(b)
1256 		{
1257 		if((v=bits2vector(b)))
1258 			{
1259 			v->bits=b;	/* only needed for savefile function */
1260 			AddVector(v, alias);
1261 			free_2(b->name);
1262 			b->name=NULL;
1263 			goto grp_bot;
1264 			}
1265 			else
1266 			{
1267 			free_2(b->name);
1268 			if(b->attribs) free_2(b->attribs);
1269 			free_2(b);
1270 			}
1271 		}
1272 		else if(!depth) /* don't try vectorized if we're re-entrant */
1273 		{
1274 		char *sp = strchr(w2, ' ');
1275 		char *lbrack;
1276 
1277 		if(sp)
1278 			{
1279 			*sp = 0;
1280 
1281 			lbrack = strrchr(w2, '[');
1282 
1283 			if(lbrack)
1284 				{
1285 				/* int made = 0; */ /* scan-build */
1286 				char *w3;
1287 				char *rbrack           = strrchr(w2,   ']');
1288 				char *rightmost_lbrack = strrchr(sp+1, '[');
1289 
1290 				if(rbrack && rightmost_lbrack)
1291 					{
1292 					*rbrack = 0;
1293 
1294 					w3 = malloc_2(strlen(w2) + 1 + strlen(rightmost_lbrack+1) + 1);
1295 					sprintf(w3, "%s:%s", w2, rightmost_lbrack+1);
1296 
1297 					/* made = */ maketraces(w3, alias, 1); /* scan-build */
1298 					free_2(w3);
1299 					}
1300 
1301 #if 0
1302 				/* this is overkill for now with possible delay implications so commented out */
1303 				if(!made)
1304 					{
1305 					*lbrack = 0;
1306 					fprintf(stderr, "GTKWAVE | Attempting regex '%s' on missing stranded vector\n", w2);
1307 
1308 					w3 = malloc_2(1 + strlen(w2) + 5);
1309 					sprintf(w3, "^%s\\[.*", w2);
1310 					maketraces(w3, alias, 1);
1311 					free_2(w3);
1312 					}
1313 #endif
1314 				}
1315 			}
1316 		}
1317 
1318 grp_bot:
1319         if((GLOBALS->default_flags&TR_GRP_BEGIN) && (current_grp_depth >= 0) && (current_grp_depth == GLOBALS->group_depth)) { AddBlankTrace(prefix+1); }
1320 	return(v!=NULL);
1321 	}
1322 else
1323 if(*w2=='!')
1324 	{
1325 	/* fill logical_mutex */
1326 	char ch;
1327 
1328 	for(i=0;i<6;i++)
1329 		{
1330 		ch = *(w2+i+1);
1331 		if(ch != 0)
1332 			{
1333 			if(ch=='!')
1334 				{
1335 				GLOBALS->strace_ctx->shadow_active = 0;
1336 				return(~0);
1337 				}
1338 
1339 			if((!i)&&(GLOBALS->strace_ctx->shadow_straces))
1340 				{
1341 				delete_strace_context();
1342 				}
1343 
1344 			GLOBALS->strace_ctx->shadow_logical_mutex[i] = (ch & 1);
1345 			}
1346 			else	/* in case of short read */
1347 			{
1348 			GLOBALS->strace_ctx->shadow_logical_mutex[i] = 0;
1349 			}
1350 		}
1351 
1352 	GLOBALS->strace_ctx->shadow_mark_idx_start = 0;
1353 	GLOBALS->strace_ctx->shadow_mark_idx_end = 0;
1354 
1355 	if(i==6)
1356 		{
1357 		ch = *(w2+7);
1358 		if(ch != 0)
1359 			{
1360 			if (isupper((int)(unsigned char)ch) || ch=='@')
1361 				GLOBALS->strace_ctx->shadow_mark_idx_start = ch - '@';
1362 
1363 			ch = *(w2+8);
1364 			if(ch != 0)
1365 				{
1366 				if (isupper((int)(unsigned char)ch) || ch=='@')
1367 					GLOBALS->strace_ctx->shadow_mark_idx_end = ch - '@';
1368 				}
1369 			}
1370 		}
1371 
1372 	GLOBALS->strace_ctx->shadow_active = 1;
1373 	return(~0);
1374 	}
1375 	else
1376 if(*w2=='?')
1377 	{
1378 	/* fill st->type */
1379 	if(*(w2+1)=='\"')
1380 		{
1381 		int lens = strlen(w2+2);
1382 		if(GLOBALS->strace_ctx->shadow_string) free_2(GLOBALS->strace_ctx->shadow_string);
1383 		GLOBALS->strace_ctx->shadow_string=NULL;
1384 
1385 		if(lens)
1386 			{
1387 			GLOBALS->strace_ctx->shadow_string = malloc_2(lens+1);
1388 			strcpy(GLOBALS->strace_ctx->shadow_string, w2+2);
1389 			}
1390 
1391 		GLOBALS->strace_ctx->shadow_type = ST_STRING;
1392 		}
1393 		else
1394 		{
1395 		unsigned int hex;
1396 		sscanf(w2+1, "%x", &hex);
1397 		GLOBALS->strace_ctx->shadow_type = hex;
1398 		}
1399 
1400 	return(~0);
1401 	}
1402 else if(*w2=='^')
1403 	{
1404 	if(*(w2+1) == '>')
1405 		{
1406 		GLOBALS->current_translate_proc = 0;	/* will overwrite if loadable/translatable */
1407 
1408 		if(*(w2+2) != '0')
1409 			{
1410 			  /*			char *fn = strstr(w2+3, " "); */
1411 			  char *fn = w2+2;
1412 			  while(*fn && !isspace((int)(unsigned char)*fn)) fn++;
1413 			if(fn)
1414 				{
1415 				while(*fn && isspace((int)(unsigned char)*fn)) fn++;
1416 				if(*fn && !isspace((int)(unsigned char)*fn))
1417 					{
1418 					char *rp = get_relative_adjusted_name(GLOBALS->sfn, fn, GLOBALS->lcname);
1419 					set_current_translate_proc(rp ? rp : fn);
1420 					if(rp) free_2(rp);
1421 					}
1422 				}
1423 			}
1424 		}
1425 	else
1426 	if(*(w2+1) == '<')
1427 		{
1428 		GLOBALS->current_translate_ttrans = 0;	/* will overwrite if loadable/translatable */
1429 
1430 		if(*(w2+2) != '0')
1431 			{
1432 			  /*			char *fn = strstr(w2+3, " "); */
1433 			char *fn = w2+3;
1434 			if(fn)
1435 				{
1436 				while(*fn && isspace((int)(unsigned char)*fn)) fn++;
1437 				if(*fn && !isspace((int)(unsigned char)*fn))
1438 					{
1439 					char *rp = get_relative_adjusted_name(GLOBALS->sfn, fn, GLOBALS->lcname);
1440 					set_current_translate_ttrans(rp ? rp : fn);
1441 					if(rp) free_2(rp);
1442 					}
1443 				}
1444 			}
1445 		}
1446 		else
1447 		{
1448 		GLOBALS->current_translate_file = 0;	/* will overwrite if loadable/translatable */
1449 
1450 		if(*(w2+1) != '0')
1451 			{
1452 			char *fn = strstr(w2+2, " ");
1453 			if(fn)
1454 				{
1455 				while(*fn && isspace((int)(unsigned char)*fn)) fn++;
1456 				if(*fn && !isspace((int)(unsigned char)*fn))
1457 					{
1458 					char *rp = get_relative_adjusted_name(GLOBALS->sfn, fn, GLOBALS->lcname);
1459 					set_current_translate_file(rp ? rp : fn);
1460 					if(rp) free_2(rp);
1461 					}
1462 				}
1463 			}
1464 		}
1465 	}
1466 else if (*w2 == '[')
1467   {
1468     /* Search for matching ']'.  */
1469     w2++;
1470     for (w = w2; *w; w++)
1471       if (*w == ']')
1472 	break;
1473     if (!*w)
1474       return 0;
1475 
1476     *w++ = 0;
1477     if (strcmp (w2, "size") == 0)
1478       {
1479       if(!GLOBALS->ignore_savefile_size)
1480 	{
1481 	/* Main window size.  */
1482 	int x, y;
1483 	sscanf (w, "%d %d", &x, &y);
1484 	if(!GLOBALS->block_xy_update) set_window_size (x, y);
1485 	}
1486       }
1487     else if (strcmp (w2, "pos") == 0)
1488       {
1489       if(!GLOBALS->ignore_savefile_pos)
1490 	{
1491 	/* Main window position.  */
1492 	int x, y;
1493 	sscanf (w, "%d %d", &x, &y);
1494 	if(!GLOBALS->block_xy_update) set_window_xypos (x, y);
1495 	}
1496       }
1497     else if (strcmp (w2, "sst_width") == 0)
1498       {
1499       if(!GLOBALS->ignore_savefile_pane_pos)
1500 	{
1501 	/* sst vs rhs of window position.  */
1502 	int x;
1503 	sscanf (w, "%d", &x);
1504 	if(!GLOBALS->block_xy_update)
1505 		{
1506 		if(GLOBALS->toppanedwindow)
1507 			{
1508 #if GTK_CHECK_VERSION(2,4,0)
1509 			gtk_paned_set_position(GTK_PANED(GLOBALS->toppanedwindow), x);
1510 #endif
1511 			}
1512 			else
1513 			{
1514 			GLOBALS->toppanedwindow_size_cache = x;
1515 			}
1516 		}
1517 	}
1518       }
1519     else if (strcmp (w2, "signals_width") == 0)
1520       {
1521       if(!GLOBALS->ignore_savefile_pane_pos)
1522 	{
1523 	/* signals vs waves panes position.  */
1524 	int x;
1525 	sscanf (w, "%d", &x);
1526 	if(!GLOBALS->block_xy_update)
1527 		{
1528 		if(GLOBALS->panedwindow)
1529 			{
1530 #if GTK_CHECK_VERSION(2,4,0)
1531 			gtk_paned_set_position(GTK_PANED(GLOBALS->panedwindow), x);
1532 #endif
1533 			}
1534 			else
1535 			{
1536 			GLOBALS->panedwindow_size_cache = x;
1537 			}
1538 		}
1539 	}
1540       }
1541     else if (strcmp (w2, "sst_expanded") == 0)
1542       {
1543       if(!GLOBALS->ignore_savefile_pane_pos)
1544 	{
1545 	/* sst is expanded?  */
1546 	int x;
1547 	sscanf (w, "%d", &x);
1548 	GLOBALS->sst_expanded = (x != 0);
1549 #if GTK_CHECK_VERSION(2,4,0)
1550 	if(!GLOBALS->block_xy_update)
1551 		{
1552 		if(GLOBALS->expanderwindow)
1553 			{
1554 			gtk_expander_set_expanded(GTK_EXPANDER(GLOBALS->expanderwindow), GLOBALS->sst_expanded);
1555 			}
1556 		}
1557 #endif
1558 	}
1559       }
1560     else if (strcmp (w2, "sst_vpaned_height") == 0)
1561       {
1562       if(!GLOBALS->ignore_savefile_pane_pos)
1563 	{
1564 	/* signals vs waves panes position.  */
1565 	int x;
1566 	sscanf (w, "%d", &x);
1567 	if(!GLOBALS->block_xy_update)
1568 		{
1569 		if(GLOBALS->sst_vpaned)
1570 			{
1571 #if GTK_CHECK_VERSION(2,4,0)
1572 			gtk_paned_set_position(GTK_PANED(GLOBALS->sst_vpaned), x);
1573 #endif
1574 			}
1575 			else
1576 			{
1577 			GLOBALS->vpanedwindow_size_cache = x;
1578 			}
1579 		}
1580 	}
1581       }
1582     else if (strcmp (w2, "color") == 0)
1583       {
1584       int which_col = 0;
1585       sscanf (w, "%d", &which_col);
1586       if((which_col>=0)&&(which_col<=WAVE_NUM_RAINBOW))
1587 		{
1588 		GLOBALS->which_t_color = which_col;
1589 		}
1590 		else
1591 		{
1592 		GLOBALS->which_t_color = 0;
1593 		}
1594       }
1595     else if (strcmp (w2, "fpshift_count") == 0)
1596       {
1597       int fpshift_count = 0;
1598       sscanf (w, "%d", &fpshift_count);
1599       if((fpshift_count<0)||(fpshift_count>255))
1600 		{
1601 		fpshift_count = 0;
1602 		}
1603       GLOBALS->default_fpshift = fpshift_count;
1604       }
1605     else if (strcmp (w2, "pattern_trace") == 0)
1606       {
1607       int which_ctx = 0;
1608       sscanf (w, "%d", &which_ctx);
1609       if((which_ctx>=0)&&(which_ctx<WAVE_NUM_STRACE_WINDOWS))
1610 		{
1611 		GLOBALS->strace_ctx = &GLOBALS->strace_windows[GLOBALS->strace_current_window = which_ctx];
1612 		}
1613       }
1614     else if (strcmp (w2, "ruler") == 0)
1615       {
1616       GLOBALS->ruler_origin = GLOBALS->ruler_step = LLDescriptor(0);
1617       sscanf(w, TTFormat" "TTFormat, &GLOBALS->ruler_origin, &GLOBALS->ruler_step);
1618       }
1619     else if (strcmp (w2, "timestart") == 0)
1620       {
1621       sscanf(w, TTFormat, &GLOBALS->timestart_from_savefile);
1622       GLOBALS->timestart_from_savefile_valid = 1;
1623       }
1624 #if WAVE_USE_GTK2
1625     else if (strcmp (w2, "treeopen") == 0)
1626 	{
1627 	while(*w)
1628 		{
1629 		if(!isspace((int)(unsigned char)*w))
1630 			{
1631 			break;
1632 			}
1633 		w++;
1634 		}
1635 
1636 	if(GLOBALS->ctree_main)
1637 		{
1638 		force_open_tree_node(w, 0, NULL);
1639 		}
1640 		else
1641 		{
1642 		/* cache values until ctree_main is created */
1643 		struct string_chain_t *t = calloc_2(1, sizeof(struct string_chain_t));
1644 		t->str = strdup_2(w);
1645 
1646 		if(!GLOBALS->treeopen_chain_curr)
1647 			{
1648 			GLOBALS->treeopen_chain_head = GLOBALS->treeopen_chain_curr = t;
1649 			}
1650 			else
1651 			{
1652 			GLOBALS->treeopen_chain_curr->next = t;
1653 			GLOBALS->treeopen_chain_curr = t;
1654 			}
1655 		}
1656 	}
1657 #endif
1658     else if (strcmp (w2, "markername") == 0)
1659 	{
1660 	char *pnt = w;
1661 	int which;
1662 
1663 	if((*pnt) && (isspace((int)(unsigned char)*pnt))) pnt++;
1664 
1665 	if(*pnt)
1666 		{
1667 		which = (*pnt) - 'A';
1668 		if((which >=0) && (which < WAVE_NUM_NAMED_MARKERS))
1669 			{
1670 			pnt++;
1671 
1672 			if(*pnt)
1673 				{
1674 				if(GLOBALS->marker_names[which]) free_2(GLOBALS->marker_names[which]);
1675 				GLOBALS->marker_names[which] = strdup_2(pnt);
1676 				}
1677 			}
1678 		}
1679 	}
1680     else if (strcmp (w2, "markername_long") == 0)
1681 	{
1682 	char *pnt = w;
1683 	int which;
1684 
1685 	if((*pnt) && (isspace((int)(unsigned char)*pnt))) pnt++;
1686 
1687 	if(*pnt)
1688 		{
1689 		char *pnt2 = strchr(pnt, ' ');
1690 		if(pnt2)
1691 			{
1692 			*pnt2 = 0;
1693 			which = bijective_marker_id_string_hash(pnt);
1694 			if((which >=0) && (which < WAVE_NUM_NAMED_MARKERS))
1695 				{
1696 				pnt = pnt2 + 1;
1697 				if((*pnt) && (isspace((int)(unsigned char)*pnt))) pnt++;
1698 
1699 				if(*pnt)
1700 					{
1701 					if(GLOBALS->marker_names[which]) free_2(GLOBALS->marker_names[which]);
1702 					GLOBALS->marker_names[which] = strdup_2(pnt);
1703 					}
1704 				}
1705 			}
1706 		}
1707 	}
1708     else if (strcmp (w2, "dumpfile") == 0)
1709 	{
1710         /* nothing here currently...only finder/DnD processes these externally */
1711         }
1712     else if (strcmp (w2, "savefile") == 0)
1713 	{
1714         /* store name for relative name processing of filters */
1715 	char *lhq = strchr(w, '"');
1716 	char *rhq = strrchr(w, '"');
1717 
1718 	if(GLOBALS->sfn)
1719 		{
1720 		free_2(GLOBALS->sfn); GLOBALS->sfn = NULL;
1721 		}
1722 
1723 	if((lhq) && (rhq) && (lhq != rhq)) /* no real need to check rhq != NULL*/
1724 		{
1725 		*rhq = 0;
1726 		GLOBALS->sfn = strdup_2(lhq + 1);
1727 		}
1728         }
1729     else if (strcmp (w2, "transaction_args") == 0)
1730 	{
1731 	char *lhq = strchr(w, '"');
1732 	char *rhq = strrchr(w, '"');
1733 
1734 	if(GLOBALS->ttranslate_args)
1735 		{
1736 		free_2(GLOBALS->ttranslate_args); GLOBALS->ttranslate_args = NULL;
1737 		}
1738 
1739 	if((lhq) && (rhq) && (lhq != rhq)) /* no real need to check rhq != NULL*/
1740 		{
1741 		*rhq = 0;
1742 		GLOBALS->ttranslate_args = strdup_2(lhq + 1);
1743 		}
1744         }
1745     else if (strcmp (w2, "*") == 0)
1746 	{
1747         /* reserved for [*] comment lines */
1748         }
1749     else
1750       {
1751 	/* Unknown attribute.  Forget it.  */
1752 	return 0;
1753       }
1754   }
1755 	else
1756 	{
1757 	int rc = maketraces(w, alias, 0);
1758 
1759 	if(rc)
1760 		{
1761 		return(rc);
1762 		}
1763 		else
1764 		{
1765 		char *newl = synth_blastvec(w);
1766 
1767 		if(newl)
1768 			{
1769 			rc = parsewavline(newl, alias, depth+1);
1770 			free_2(newl);
1771 			}
1772 
1773 		/* prevent malformed group openings [missing group opening] from keeping other signals from displaying */
1774 		if((!rc)&&(GLOBALS->default_flags&TR_GRP_BEGIN))
1775 			{
1776 			AddBlankTrace(w);
1777 			rc = ~0;
1778 			}
1779 
1780 		return(rc);
1781 		}
1782 	}
1783 
1784 return(0);
1785 }
1786 
1787 /******************************************************************/
1788 
1789 /****************/
1790 /* LX2 variants */
1791 /****************/
1792 
1793 /*
1794  * Make solitary traces from wildcarded signals...
1795  */
maketraces_lx2(char * str,char * alias,int quick_return)1796 int maketraces_lx2(char *str, char *alias, int quick_return)
1797 {
1798 (void)alias;
1799 
1800 char *pnt, *wild;
1801 char ch, wild_active=0;
1802 int len;
1803 int i;
1804 int made = 0;
1805 
1806 pnt=str;
1807 while((ch=*pnt))
1808 	{
1809 	if(ch=='*')
1810 		{
1811 		wild_active=1;
1812 		break;
1813 		}
1814 	pnt++;
1815 	}
1816 
1817 if(!wild_active)	/* short circuit wildcard evaluation with bsearch */
1818 	{
1819 	struct symbol *s;
1820 
1821 	if(str[0]=='(')
1822 		{
1823 		for(i=1;;i++)
1824 			{
1825 			if(str[i]==0) return(0);
1826 			if((str[i]==')')&&(str[i+1])) {i++; break; }
1827 			}
1828 
1829 		if((s=symfind(str+i, NULL)))
1830 			{
1831 			lx2_set_fac_process_mask(s->n);
1832 			made = ~0;
1833 			}
1834 		return(made);
1835 		}
1836 		else
1837 		{
1838 		if((s=symfind(str, NULL)))
1839 			{
1840 			lx2_set_fac_process_mask(s->n);
1841 			made = ~0;
1842 			}
1843 		return(made);
1844 		}
1845 	}
1846 
1847 while(1)
1848 {
1849 pnt=str;
1850 len=0;
1851 
1852 while(1)
1853 	{
1854 	ch=*pnt++;
1855 	if(isspace((int)(unsigned char)ch)||(!ch)) break;
1856 	len++;
1857 	}
1858 
1859 if(len)
1860 	{
1861 	wild=(char *)calloc_2(1,len+1);
1862 	memcpy(wild,str,len);
1863 	wave_regex_compile(wild, WAVE_REGEX_WILD);
1864 
1865 	for(i=0;i<GLOBALS->numfacs;i++)
1866 		{
1867 		if(wave_regex_match(GLOBALS->facs[i]->name, WAVE_REGEX_WILD))
1868 			{
1869 			lx2_set_fac_process_mask(GLOBALS->facs[i]->n);
1870 			made = ~0;
1871 			if(quick_return) break;
1872 			}
1873 		}
1874 
1875 	free_2(wild);
1876 	}
1877 
1878 if(!ch) break;
1879 str=pnt;
1880 }
1881 return(made);
1882 }
1883 
1884 
1885 /*
1886  * Create a vector from wildcarded signals...
1887  */
makevec_lx2(char * str)1888 int makevec_lx2(char *str)
1889 {
1890 char *pnt, *pnt2, *wild=NULL;
1891 char ch, ch2, wild_active;
1892 int len;
1893 int i;
1894 int rc = 0;
1895 
1896 while(1)
1897 {
1898 pnt=str;
1899 len=0;
1900 
1901 while(1)
1902 	{
1903 	ch=*pnt++;
1904 	if(isspace((int)(unsigned char)ch)||(!ch)) break;
1905 	len++;
1906 	}
1907 
1908 if(len)
1909 	{
1910 	wild=(char *)calloc_2(1,len+1);
1911 	memcpy(wild,str,len);
1912 
1913 	DEBUG(printf("WILD: %s\n",wild));
1914 
1915 	wild_active=0;
1916 	pnt2=wild;
1917 	while((ch2=*pnt2))
1918 		{
1919 		if(ch2=='*')
1920 			{
1921 			wild_active=1;
1922 			break;
1923 			}
1924 		pnt2++;
1925 		}
1926 
1927 	if(!wild_active)	/* short circuit wildcard evaluation with bsearch */
1928 		{
1929 		struct symbol *s;
1930 		if(wild[0]=='(')
1931 			{
1932 			for(i=1;;i++)
1933 				{
1934 				if(wild[i]==0) break;
1935 				if((wild[i]==')')&&(wild[i+1]))
1936 					{
1937 					i++;
1938 					s=symfind(wild+i, NULL);
1939 					if(s)
1940 						{
1941 						lx2_set_fac_process_mask(s->n);
1942 						rc = 1;
1943 						}
1944 					break;
1945 					}
1946 				}
1947 			}
1948 			else
1949 			{
1950 			if((s=symfind(wild, NULL)))
1951 				{
1952 				lx2_set_fac_process_mask(s->n);
1953 				rc = 1;
1954 				}
1955 			}
1956 		}
1957 		else
1958 		{
1959 		wave_regex_compile(wild, WAVE_REGEX_WILD);
1960 		for(i=GLOBALS->numfacs-1;i>=0;i--)	/* to keep vectors in little endian hi..lo order */
1961 			{
1962 			if(wave_regex_match(GLOBALS->facs[i]->name, WAVE_REGEX_WILD))
1963 				{
1964 				lx2_set_fac_process_mask(GLOBALS->facs[i]->n);
1965 				rc = 1;
1966 				}
1967 			}
1968 		}
1969 	free_2(wild);
1970 	}
1971 
1972 if(!ch) break;
1973 str=pnt;
1974 }
1975 
1976 return(rc);
1977 }
1978 
1979 
1980 /*
1981  * Parse a line of the wave file and act accordingly..
1982  * Returns nonzero if trace(s) added.
1983  */
parsewavline_lx2(char * w,char * alias,int depth)1984 int parsewavline_lx2(char *w, char *alias, int depth)
1985 {
1986   int made = 0;
1987   int i;
1988   int len;
1989   char *w2;
1990   char *prefix, *suffix, *new;
1991   char *prefix_init, *w2_init;
1992   unsigned int mode;
1993 
1994 
1995   if(!(len=strlen(w))) return(0);
1996   if(*(w+len-1)=='\n')
1997     {
1998       *(w+len-1)=0x00; /* strip newline if present */
1999       len--;
2000       if(!len) return(0);
2001     }
2002 
2003   while(1)
2004     {
2005       if(isspace((int)(unsigned char)*w)) { w++; continue; }
2006       if(!(*w)) return(0);	/* no args */
2007       break;			/* start grabbing chars from here */
2008     }
2009 
2010   w2=w;
2011 
2012 /* sscanf(w2,"%s",prefix); */
2013 
2014  prefix=(char *)wave_alloca(len+1);
2015  suffix=(char *)wave_alloca(len+1);
2016  new=(char *)wave_alloca(len+1);
2017  new[0] = 0; /* scan-build : in case there are weird mode problems */
2018 
2019  prefix_init = prefix;
2020  w2_init = new;
2021  mode = 0; /* 0 = before "{", 1 = after "{", 2 = after "}" or " " */
2022 
2023  while(*w2)
2024    {
2025      if((mode == 0) && (*w2 == '{'))
2026        {
2027 	 mode = 1;
2028 	 w2++;
2029        }
2030      else if((mode == 1) && (*w2 == '}'))
2031        {
2032 
2033 	 *(prefix) = '\0';
2034 	 mode = 2;
2035 	 w2++;
2036        }
2037      else if((mode == 0) && (*w2 == ' '))
2038        {
2039 	 *(prefix) = '\0';
2040 	 strcpy(new, w2);
2041 	 mode = 2;
2042 	 w2++;
2043 	 new++;
2044        }
2045      else
2046        {
2047 	 strcpy(new, w2);
2048 	 if (mode != 2)
2049 	   {
2050 	     strcpy(prefix, w2);
2051 	     prefix++;
2052 	   }
2053 	 w2++;
2054 	 new++;
2055        }
2056    }
2057 
2058  prefix = prefix_init;
2059  w2 = w2_init;
2060 
2061  /* printf("IIIII |%s| %s\n", prefix, w2); */
2062 
2063 if(*w2=='[')
2064 	{
2065 	}
2066 else
2067 if(*w2=='*')
2068 	{
2069 	}
2070 else
2071 if(*w2=='-')
2072 	{
2073 	}
2074 else
2075 if(*w2=='>')
2076 	{
2077 	}
2078 else
2079 if(*w2=='@')
2080 	{
2081 	}
2082 else
2083 if(*w2=='+')
2084 	{
2085 	/* handle aliasing */
2086 	struct symbol *s;
2087 	sscanf(w2+strlen(prefix),"%s",suffix);
2088 
2089 	if(suffix[0]=='(')
2090 		{
2091 		for(i=1;;i++)
2092 			{
2093 			if(suffix[i]==0) return(0);
2094 			if((suffix[i]==')')&&(suffix[i+1])) {i++; break; }
2095 			}
2096 
2097 		s=symfind(suffix+i, NULL);
2098 		if(s)
2099 			{
2100 			lx2_set_fac_process_mask(s->n);
2101 			made = ~0;
2102 			}
2103                 else
2104                         {
2105                         char *lp = strrchr(suffix+i, '[');
2106 			if(lp)
2107 				{
2108 				char *ns = malloc_2(strlen(suffix+i) + 32);
2109 				char *colon = strchr(lp+1, ':');
2110 				int msi, lsi, bval, actual;
2111 				*lp = 0;
2112 
2113 				bval = atoi(suffix+1);
2114 				if(colon)
2115 					{
2116 					msi = atoi(lp+1);
2117 					lsi = atoi(colon+1);
2118 
2119 					if(lsi > msi)
2120 						{
2121 						actual = msi + bval;
2122 						}
2123 						else
2124 						{
2125 						actual = msi - bval;
2126 						}
2127 					}
2128 					else
2129 					{
2130 					actual = bval; /* punt */
2131 					}
2132 
2133 				sprintf(ns, "%s[%d]", suffix+i, actual);
2134 				*lp = '[';
2135 
2136 				s=symfind(ns, NULL);
2137 				free_2(ns);
2138 				if(s)
2139 					{
2140 	                                lx2_set_fac_process_mask(s->n);
2141 	                                made = ~0;
2142 					}
2143 				}
2144 			}
2145 
2146 		return(made);
2147 		}
2148 	else
2149 	  {
2150 	    int rc;
2151 	    char *newl   = strdup_2(w2+strlen(prefix));
2152 	    char *nalias = strdup_2(prefix+1);
2153 
2154 	    rc = parsewavline_lx2(newl, nalias, depth);
2155 	    if (newl)   free_2(newl);
2156 	    if (nalias) free_2(nalias);
2157 
2158 	    return rc;
2159 	  }
2160 
2161 	/* 	{ */
2162 /* 		if((s=symfind(suffix, NULL))) */
2163 /* 			{ */
2164 /* 			lx2_set_fac_process_mask(s->n); */
2165 /* 			made = ~0; */
2166 /* 			} */
2167 /* 		return(made); */
2168 /* 		} */
2169 	}
2170 else
2171 if((*w2=='#')||(*w2==':'))
2172 	{
2173 	int rc;
2174 
2175 	/* handle bitvec, parsing extra time info and such is inefficient but ok for ":" case */
2176 	w2=w2+strlen(prefix);
2177 	while(1)
2178 		{
2179 		if(isspace((int)(unsigned char)*w2)) { w2++; continue; }
2180 		if(!(*w2)) return(0);	/* no more args */
2181 		break;			/* start grabbing chars from here */
2182 		}
2183 
2184 	rc = makevec_lx2(w2);
2185 	if((!rc)&&(!depth))		/* don't try vectorized if we're re-entrant */
2186 		{
2187 		char *sp = strchr(w2, ' ');
2188 		char *lbrack;
2189 
2190 		if(sp)
2191 			{
2192 			*sp = 0;
2193 
2194 			lbrack = strrchr(w2, '[');
2195 
2196 			if(lbrack)
2197 				{
2198 				char *w3;
2199 				char *rbrack           = strrchr(w2,   ']');
2200 				char *rightmost_lbrack = strrchr(sp+1, '[');
2201 
2202 				if(rbrack && rightmost_lbrack)
2203 					{
2204 					*rbrack = 0;
2205 
2206 					w3 = malloc_2(strlen(w2) + 1 + strlen(rightmost_lbrack+1) + 1);
2207 					sprintf(w3, "%s:%s", w2, rightmost_lbrack+1);
2208 
2209 					made = maketraces_lx2(w3, alias, 1);
2210 					free_2(w3);
2211 					}
2212 
2213 				if(0)	/* this is overkill for now with possible delay implications so commented out */
2214 				if(!made)
2215 					{
2216 					*lbrack = 0;
2217 
2218 					w3 = malloc_2(1 + strlen(w2) + 5);
2219 					sprintf(w3, "^%s\\[.*", w2);
2220 					maketraces_lx2(w3, alias, 1);
2221 					free_2(w3);
2222 					}
2223 				}
2224 			}
2225 		}
2226 
2227 	return(made);
2228 	}
2229 else
2230 if(*w2=='!')
2231 	{
2232 	}
2233 	else
2234 if(*w2=='?')
2235 	{
2236 	}
2237 else if(*w2=='^')
2238 	{
2239 	}
2240 	else
2241 	{
2242 	  made = maketraces_lx2(w, alias, 0);
2243         if(!made)
2244                 {
2245                 char *newl = synth_blastvec(w);
2246 
2247 		if(newl)
2248 			{
2249 	                made = parsewavline_lx2(newl, alias, depth+1);
2250 	                free_2(newl);
2251 			}
2252                 }
2253 	}
2254 
2255 return(made);
2256 }
2257 
2258 /******************************************************************/
2259 
2260 /* GetRelativeFilename(), by Rob Fisher.
2261  * rfisher@iee.org
2262  * http://come.to/robfisher
2263  */
2264 
2265 #define MAX_FILENAME_LEN PATH_MAX
2266 
2267 /* The number of characters at the start of an absolute filename.  e.g. in DOS,
2268  * absolute filenames start with "X:\" so this value should be 3, in UNIX they start
2269  * with "\" so this value should be 1.
2270  */
2271 #if defined _MSC_VER || defined __MINGW32__
2272 #define ABSOLUTE_NAME_START 3
2273 #else
2274 #define ABSOLUTE_NAME_START 1
2275 #endif
2276 
2277 /* set this to '\\' for DOS or '/' for UNIX */
2278 #if defined _MSC_VER || defined __MINGW32__
2279 #define SLASH '\\'
2280 #else
2281 #define SLASH '/'
2282 #endif
2283 
2284 /* Given the absolute current directory and an absolute file name, returns a relative file name.
2285  * For example, if the current directory is C:\foo\bar and the filename C:\foo\whee\text.txt is given,
2286  * GetRelativeFilename will return ..\whee\text.txt.
2287  */
GetRelativeFilename(char * currentDirectory,char * absoluteFilename,int * dotdot_levels)2288 char* GetRelativeFilename(char *currentDirectory, char *absoluteFilename, int *dotdot_levels)
2289 {
2290 	int afMarker = 0, rfMarker = 0;
2291 	int cdLen = 0, afLen = 0;
2292 	int i = 0;
2293 	int levels = 0;
2294 	static char relativeFilename[MAX_FILENAME_LEN+1];
2295 
2296 	*dotdot_levels = 0;
2297 
2298 	cdLen = strlen(currentDirectory);
2299 	afLen = strlen(absoluteFilename);
2300 
2301 	/* make sure the names are not too long or too short */
2302 	if(cdLen > MAX_FILENAME_LEN || cdLen < ABSOLUTE_NAME_START+1 ||
2303 		afLen > MAX_FILENAME_LEN || afLen < ABSOLUTE_NAME_START+1)
2304 	{
2305 		return(NULL);
2306 	}
2307 
2308 	/* Handle DOS names that are on different drives: */
2309 	if(currentDirectory[0] != absoluteFilename[0])
2310 	{
2311 		/* not on the same drive, so only absolute filename will do */
2312 		strcpy(relativeFilename, absoluteFilename);
2313 		return(relativeFilename);
2314 	}
2315 
2316 	/* they are on the same drive, find out how much of the current directory
2317 	 * is in the absolute filename
2318          */
2319 	i = ABSOLUTE_NAME_START;
2320 	while(i < afLen && i < cdLen && currentDirectory[i] == absoluteFilename[i])
2321 	{
2322 		i++;
2323 	}
2324 
2325 	if(i == cdLen && (absoluteFilename[i] == SLASH || absoluteFilename[i-1] == SLASH))
2326 	{
2327 		/* the whole current directory name is in the file name,
2328 		 * so we just trim off the current directory name to get the
2329 		 * current file name.
2330 		 */
2331 		if(absoluteFilename[i] == SLASH)
2332 		{
2333 			/* a directory name might have a trailing slash but a relative
2334 			 * file name should not have a leading one...
2335 			 */
2336 			i++;
2337 		}
2338 
2339 		strcpy(relativeFilename, &absoluteFilename[i]);
2340 		return(relativeFilename);
2341 	}
2342 
2343 
2344 	/* The file is not in a child directory of the current directory, so we
2345 	 * need to step back the appropriate number of parent directories by
2346 	 * using "..\"s.  First find out how many levels deeper we are than the
2347 	 * common directory
2348 	 */
2349 	afMarker = i;
2350 	levels = 1;
2351 
2352 	/* count the number of directory levels we have to go up to get to the
2353 	 * common directory
2354 	 */
2355 	while(i < cdLen)
2356 	{
2357 		i++;
2358 		if(currentDirectory[i] == SLASH)
2359 		{
2360 			/* make sure it's not a trailing slash */
2361 			i++;
2362 			if(currentDirectory[i] != '\0')
2363 			{
2364 				levels++;
2365 			}
2366 		}
2367 	}
2368 
2369 	/* move the absolute filename marker back to the start of the directory name
2370 	 * that it has stopped in.
2371 	 */
2372 	while(afMarker > 0 && absoluteFilename[afMarker-1] != SLASH)
2373 	{
2374 		afMarker--;
2375 	}
2376 
2377 	/* check that the result will not be too long */
2378 	if(levels * 3 + afLen - afMarker > MAX_FILENAME_LEN)
2379 	{
2380 		return(NULL);
2381 	}
2382 
2383 	/* add the appropriate number of "..\"s. */
2384 	rfMarker = 0;
2385 	*dotdot_levels = levels;
2386 	for(i = 0; i < levels; i++)
2387 	{
2388 		relativeFilename[rfMarker++] = '.';
2389 		relativeFilename[rfMarker++] = '.';
2390 		relativeFilename[rfMarker++] = SLASH;
2391 	}
2392 
2393 	/* copy the rest of the filename into the result string */
2394 	strcpy(&relativeFilename[rfMarker], &absoluteFilename[afMarker]);
2395 
2396 	return(relativeFilename);
2397 }
2398 
2399 /******************************************************************/
2400 
2401 #ifdef __MINGW32__
find_dumpfile_scrub_slashes(char * s)2402 static void find_dumpfile_scrub_slashes(char *s)
2403 {
2404 if(s)
2405 	{
2406 	while(*s)
2407 		{
2408 		if(*s == '/') *s = '\\';
2409 		s++;
2410 		}
2411 	}
2412 }
2413 #else
find_dumpfile_scrub_slashes(char * s)2414 static void find_dumpfile_scrub_slashes(char *s)
2415 {
2416 if(s)
2417 	{
2418 	if(s[0] && s[1] && s[2] && (s[1] == ':') && (s[2] == '\\'))
2419 		{
2420 		while(*s)
2421 			{
2422 			if(*s == '\\') *s = '/';
2423 			s++;
2424 			}
2425 		}
2426 	}
2427 }
2428 #endif
2429 
2430 
find_dumpfile_2(char * orig_save,char * orig_dump,char * this_save)2431 char *find_dumpfile_2(char *orig_save, char *orig_dump, char *this_save)
2432 {
2433 char *synth_nam = NULL;
2434 
2435 if(orig_save && orig_dump && this_save)
2436 	{
2437 	char *dup_orig_save;
2438 	char *rhs_orig_save_slash;
2439 	char *grf = NULL;
2440 	int dotdot_levels = 0;
2441 
2442 	find_dumpfile_scrub_slashes(orig_save);
2443 	find_dumpfile_scrub_slashes(orig_dump);
2444 	find_dumpfile_scrub_slashes(this_save);
2445 
2446 	dup_orig_save = strdup_2(orig_save);
2447 	rhs_orig_save_slash = strrchr(dup_orig_save, SLASH);
2448 
2449 	if(rhs_orig_save_slash)
2450 		{
2451 		*rhs_orig_save_slash = 0;
2452 		grf =GetRelativeFilename(dup_orig_save, orig_dump, &dotdot_levels);
2453 		if(grf)
2454 			{
2455 			char *dup_this_save = strdup_2(this_save);
2456 			char *rhs_this_save_slash = strrchr(dup_this_save, SLASH);
2457 			char *p = dup_this_save;
2458 			int levels = 0;
2459 
2460 			if(rhs_this_save_slash)
2461 				{
2462 				*(rhs_this_save_slash+1) = 0;
2463 
2464 				while(*p)
2465 					{
2466 					if(*p == SLASH) levels++;
2467 					p++;
2468 					}
2469 
2470 				if(levels > dotdot_levels) /* > because we left the ending slash on dup_this_save */
2471 					{
2472 					synth_nam = malloc_2(strlen(dup_this_save) + strlen(grf) + 1);
2473 					strcpy(synth_nam, dup_this_save);
2474 					strcat(synth_nam, grf);
2475 					}
2476 				}
2477 
2478 			free_2(dup_this_save);
2479 			}
2480 
2481 		}
2482 
2483 	free_2(dup_orig_save);
2484 	}
2485 
2486 return(synth_nam);
2487 }
2488 
2489 
find_dumpfile(char * orig_save,char * orig_dump,char * this_save)2490 char *find_dumpfile(char *orig_save, char *orig_dump, char *this_save)
2491 {
2492 char *dfile = NULL;
2493 
2494 dfile = find_dumpfile_2(orig_save, orig_dump, this_save);
2495 if(!dfile && orig_save && orig_dump)
2496         {
2497 	const char *pfx = "/././";
2498         int pfxlen = strlen(pfx);
2499         char *orig_save2 = malloc_2(strlen(orig_save) + pfxlen + 1);
2500         char *orig_dump2 = malloc_2(strlen(orig_dump) + pfxlen + 1);
2501 
2502 	strcpy(orig_save2, pfx); strcat(orig_save2, orig_save);
2503         strcpy(orig_dump2, pfx); strcat(orig_dump2, orig_dump);
2504 
2505         dfile = find_dumpfile_2(orig_save2, orig_dump2, this_save);
2506         if(!dfile)
2507                 {
2508                 free_2(orig_dump2);
2509                 free_2(orig_save2);
2510                 }
2511         }
2512 
2513 return(dfile);
2514 }
2515 
2516 /******************************************************************/
2517 
2518 /*
2519  * deliberately kept outside of GLOBALS control
2520  */
2521 struct finder_file_chain
2522 {
2523 struct finder_file_chain *next;
2524 unsigned queue_warning_presented : 1;
2525 unsigned save_file_only : 1;
2526 char *name;
2527 };
2528 
2529 static struct finder_file_chain *finder_name_integration = NULL;
2530 
2531 /*
2532  * called in timer routine
2533  */
process_finder_names_queued(void)2534 gboolean process_finder_names_queued(void)
2535 {
2536 return(finder_name_integration != NULL);
2537 }
2538 
process_finder_extract_queued_name(void)2539 char *process_finder_extract_queued_name(void)
2540 {
2541 struct finder_file_chain *lc = finder_name_integration;
2542 while(lc)
2543 	{
2544 	if(!lc->queue_warning_presented)
2545 		{
2546 		lc->queue_warning_presented = 1;
2547 		return(lc->name);
2548 		}
2549 
2550 	lc = lc->next;
2551 	}
2552 
2553 return(NULL);
2554 }
2555 
process_finder_name_integration(void)2556 gboolean process_finder_name_integration(void)
2557 {
2558 static int is_working = 0;
2559 struct finder_file_chain *lc = finder_name_integration;
2560 struct finder_file_chain *lc_next;
2561 
2562 if(lc && !is_working)
2563 	{
2564 	is_working = 1;
2565 	finder_name_integration = NULL; /* placed here to avoid race conditions with GLOBALS */
2566 
2567 	while(lc)
2568 		{
2569 		char *lcname = lc->name;
2570 		int try_to_load_file = 1;
2571 		int reload_save_file = 0;
2572 		char *dfn = NULL;
2573 		char *sfn = NULL;
2574 		char *fdf = NULL;
2575 		FILE *f;
2576 		off_t dumpsiz = -1;
2577 		time_t dumptim = -1;
2578 		int optimize_vcd = 0;
2579 
2580 		if ((suffix_check(lcname, ".sav")) || (suffix_check(lcname, ".gtkw")))
2581 			{
2582 			reload_save_file = 1;
2583 			try_to_load_file = 0;
2584 
2585 			if(!lc->save_file_only)
2586 				{
2587 				read_save_helper(lcname, &dfn, &sfn, &dumpsiz, &dumptim, &optimize_vcd);
2588 
2589 				if(dfn)
2590 					{
2591 					char *old_dfn = dfn;
2592 					dfn = wave_alloca(strlen(dfn)+1); /* as context can change on file load */
2593 					strcpy(dfn, old_dfn);
2594 					free_2(old_dfn);
2595 					}
2596 
2597 				if(sfn)
2598 					{
2599 					char *old_sfn = sfn;
2600 					sfn = wave_alloca(strlen(sfn)+1); /* as context can change on file load */
2601 					strcpy(sfn, old_sfn);
2602 					free_2(old_sfn);
2603 					}
2604 
2605 
2606 #if defined __USE_BSD || defined __USE_XOPEN_EXTENDED || defined __CYGWIN__ || defined HAVE_REALPATH
2607 		               	if(dfn && sfn)
2608 	              			{
2609 		                        char *can = realpath_2(lcname, NULL);
2610 		                        char *old_fdf = find_dumpfile(sfn, dfn, can);
2611 
2612 		                        free(can);
2613 					fdf = wave_alloca(strlen(old_fdf)+1);
2614 					strcpy(fdf, old_fdf);
2615 					free_2(old_fdf);
2616 
2617 		                       	f = fopen(fdf, "rb");
2618 		                        if(f)
2619 		                                {
2620 		                                fclose(f);
2621 		                                lcname = fdf;
2622 						try_to_load_file = 1;
2623 		                               	}
2624 					}
2625 #endif
2626 
2627 				if(dfn && !try_to_load_file)
2628 					{
2629 					f = fopen(dfn, "rb");
2630 					if(f)
2631 						{
2632 						fclose(f);
2633 						lcname = dfn;
2634 						try_to_load_file = 1;
2635 						}
2636 					}
2637 				}
2638 			}
2639 
2640 		if(try_to_load_file)
2641 			{
2642 			int plen = strlen(lcname);
2643 			char *fni = wave_alloca(plen + 32); /* extra space for message */
2644 
2645 			sprintf(fni, "Loading %s...", lcname);
2646 			wave_gtk_window_set_title(GTK_WINDOW(GLOBALS->mainwindow), fni, GLOBALS->dumpfile_is_modified ? WAVE_SET_TITLE_MODIFIED: WAVE_SET_TITLE_NONE, 0);
2647 
2648 			strcpy(fni, lcname);
2649 
2650 			if(!menu_new_viewer_tab_cleanup_2(fni, optimize_vcd))
2651 				{
2652 				}
2653 				else
2654 				{
2655 				GLOBALS->dumpfile_is_modified = 0;
2656 #ifdef HAVE_SYS_STAT_H
2657 				if((dumpsiz != -1) && (dumptim != -1))
2658         				{
2659 				        struct stat sbuf;
2660 				        if(!stat(fni, &sbuf))
2661 				                {
2662 				                GLOBALS->dumpfile_is_modified = (dumpsiz != sbuf.st_size) || (dumptim != sbuf.st_mtime);
2663 				                }
2664 				        }
2665 #endif
2666 				}
2667 
2668 			wave_gtk_window_set_title(GTK_WINDOW(GLOBALS->mainwindow), GLOBALS->winname, GLOBALS->dumpfile_is_modified ? WAVE_SET_TITLE_MODIFIED: WAVE_SET_TITLE_NONE, 0);
2669 			}
2670 
2671 		/* now do save file... */
2672 		if(reload_save_file)
2673 			{
2674 			/* let any possible dealloc get taken up by free_outstanding() */
2675 			GLOBALS->filesel_writesave = strdup_2(lc->name);
2676 			read_save_helper(GLOBALS->filesel_writesave, NULL, NULL, NULL, NULL, NULL);
2677 			wave_gconf_client_set_string("/current/savefile", GLOBALS->filesel_writesave);
2678 			}
2679 
2680 		lc_next = lc->next;
2681 		g_free(lc->name);
2682 		g_free(lc);
2683 		lc = lc_next;
2684 		}
2685 
2686 	is_working = 0;
2687 	return(TRUE);
2688 	}
2689 
2690 return(FALSE);
2691 }
2692 
2693 /******************************************************************/
2694 
2695 /*
2696  * Integration with Finder...
2697  * cache name and load in later off a timer (similar to caching DnD for quartz...)
2698  */
deal_with_rpc_open_2(const gchar * path,gpointer user_data,gboolean is_save_file_only)2699 gboolean deal_with_rpc_open_2(const gchar *path, gpointer user_data, gboolean is_save_file_only)
2700 {
2701 (void)user_data;
2702 
2703 const char *suffixes[] =
2704 {
2705  ".vcd", ".evcd", ".dump",
2706  ".lxt", ".lxt2", ".lx2",
2707  ".vzt",
2708  ".fst",
2709  ".ghw",
2710 #ifdef EXTLOAD_SUFFIX
2711  EXTLOAD_SUFFIX,
2712 #endif
2713 #ifdef AET2_IS_PRESENT
2714  ".aet", ".ae2",
2715 #endif
2716 ".gtkw", ".sav"
2717 };
2718 
2719 const int num_suffixes = sizeof(suffixes) / sizeof(const char *);
2720 int i, mat = 0;
2721 
2722 for(i=0;i<num_suffixes;i++)
2723 	{
2724 	mat = suffix_check(path, suffixes[i]);
2725 	if(mat) break;
2726 	}
2727 
2728 if(!mat)
2729 	{
2730 	/* generates requester "gtkwave-bin could not open files in the 'xxx' format" */
2731 	return(FALSE);
2732 	}
2733 
2734 if(is_save_file_only)
2735 	{
2736         struct finder_file_chain *p = g_malloc(sizeof(struct finder_file_chain));
2737         p->name = g_strdup(path);
2738 	p->queue_warning_presented = 0;
2739 	p->save_file_only = 1;
2740         p->next = finder_name_integration;
2741 	finder_name_integration = p;
2742 	}
2743 	else
2744 	{
2745 	if(!finder_name_integration)
2746 	        {
2747 	        finder_name_integration = g_malloc(sizeof(struct finder_file_chain));
2748 	        finder_name_integration->name = g_strdup(path);
2749 		finder_name_integration->queue_warning_presented = 0;
2750 		finder_name_integration->save_file_only = 0;
2751 	        finder_name_integration->next = NULL;
2752 	        }
2753 	        else
2754 	        {
2755 	        struct finder_file_chain *p = finder_name_integration;
2756 	        while(p->next) p = p->next;
2757 	        p->next = g_malloc(sizeof(struct finder_file_chain));
2758 		p->next->queue_warning_presented = 0;
2759 		p->next->save_file_only = 0;
2760 	        p->next->name = g_strdup(path);
2761 	        p->next->next = NULL;
2762 	        }
2763 	}
2764 
2765 return(TRUE);
2766 }
2767 
deal_with_rpc_open(const gchar * path,gpointer user_data)2768 gboolean deal_with_rpc_open(const gchar *path, gpointer user_data)
2769 {
2770 return(deal_with_rpc_open_2(path, user_data, FALSE));
2771 }
2772 
2773 
2774 #ifdef MAC_INTEGRATION
2775 
2776 /*
2777  * block termination if in the middle of something important
2778  */
deal_with_termination(GtkosxApplication * app,gpointer user_data)2779 gboolean deal_with_termination(GtkosxApplication *app, gpointer user_data)
2780 {
2781 (void)app;
2782 (void)user_data;
2783 
2784 gboolean do_not_terminate = FALSE; /* future expansion */
2785 
2786 if(do_not_terminate)
2787         {
2788         status_text("GTKWAVE | Busy, quit signal blocked.\n");
2789         }
2790 
2791 return(do_not_terminate);
2792 }
2793 
2794 
2795 /*
2796  * Integration with Finder...
2797  * cache name and load in later off a timer (similar to caching DnD for quartz...)
2798  */
deal_with_finder_open(GtkosxApplication * app,gchar * path,gpointer user_data)2799 gboolean deal_with_finder_open(GtkosxApplication *app, gchar *path, gpointer user_data)
2800 {
2801 (void)app;
2802 
2803 return(deal_with_rpc_open(path, user_data));
2804 }
2805 
2806 #endif
2807 
2808 
suffix_check(const char * s,const char * sfx)2809 int suffix_check(const char *s, const char *sfx)
2810 {
2811 unsigned int sfxlen = strlen(sfx);
2812 return((strlen(s)>=sfxlen)&&(!strcasecmp(s+strlen(s)-sfxlen,sfx)));
2813 }
2814 
2815