1 /*
2  * Copyright (c) Tony Bybell 1999-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 
11 /*
12  * debug.c 01feb99ajb
13  * malloc debugs added on 13jul99ajb
14  * malloc tracking added on 05aug07ajb for 3.1 series
15  */
16 #include <config.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include "globals.h"
21 #include "debug.h"
22 #ifdef _WAVE_HAVE_JUDY
23 #include <Judy.h>
24 #endif
25 
26 #ifdef HAVE_SYS_STAT_H
27 #include <sys/stat.h>
28 #include "fstapi.h"
29 #include "lxt2_read.h"
30 #include "lxt.h"
31 #include "vzt_read.h"
32 #endif
33 
34 #undef free_2
35 #undef malloc_2
36 #undef realloc_2
37 #undef calloc_2
38 
39 #ifdef _WAVE_HAVE_JUDY
free_outstanding(void)40 void free_outstanding(void)
41 {
42 Pvoid_t  PJArray = (Pvoid_t)GLOBALS->alloc2_chain;
43 int rcValue;
44 Word_t Index;
45 #ifdef DEBUG_PRINTF
46 int ctr = 0;
47 
48 printf("\n*** cleanup ***\n");
49 printf("Freeing %d chunks\n", GLOBALS->outstanding);
50 system("date");
51 #endif
52 
53 if(GLOBALS->s_selected)
54 	{
55 	destroy_s_selected();
56 	}
57 
58 Index = 0;
59 for (rcValue = Judy1First(PJArray, &Index, PJE0); rcValue != 0; rcValue = Judy1Next(PJArray, &Index, PJE0))
60 	{
61 	free((void *)Index);
62 #ifdef DEBUG_PRINTF
63 	ctr++;
64 #endif
65 	}
66 Judy1FreeArray(&PJArray, PJE0);
67 
68 GLOBALS->alloc2_chain = NULL;
69 GLOBALS->outstanding = 0;
70 
71 #ifdef DEBUG_PRINTF
72 printf("Freed %d chunks\n", ctr);
73 system("date");
74 #endif
75 }
76 #else
free_outstanding(void)77 void free_outstanding(void)
78 {
79 void **t = (void **)GLOBALS->alloc2_chain;
80 void **t2;
81 int ctr = 0;
82 
83 #ifdef DEBUG_PRINTF
84 printf("\n*** cleanup ***\n");
85 printf("Freeing %d chunks\n", GLOBALS->outstanding);
86 system("date");
87 #endif
88 
89 while(t)
90 	{
91 	t2 = (void **) *(t+1);
92 	free(t);
93 	t = t2;
94 	ctr++;
95 	}
96 
97 GLOBALS->alloc2_chain = NULL;
98 GLOBALS->outstanding = 0;
99 
100 #ifdef DEBUG_PRINTF
101 printf("Freed %d chunks\n", ctr);
102 system("date");
103 #endif
104 }
105 #endif
106 
107 /*
108  * wrapped malloc family...
109  */
110 #ifdef _WAVE_HAVE_JUDY
malloc_2(size_t size,char * filename,int lineno)111 void *malloc_2(size_t size
112 #ifdef DEBUG_MALLOC_LINES
113 , char *filename, int lineno
114 #endif
115 )
116 {
117 void *ret;
118 
119 ret=malloc(size);
120 if(ret)
121         {
122 	Judy1Set ((Pvoid_t)&GLOBALS->alloc2_chain, (Word_t)ret, PJE0);
123 
124         GLOBALS->outstanding++;
125 
126         return(ret);
127         }
128         else
129         {
130 #ifdef DEBUG_MALLOC_LINES
131         fprintf(stderr, "FATAL ERROR: malloc_2() Out of memory, sorry. ['%s', %d]\n", filename, lineno);
132 #else
133         fprintf(stderr, "FATAL ERROR: malloc_2() Out of memory, sorry.\n");
134 #endif
135         exit(1);
136         }
137 }
138 #else
malloc_2(size_t size,char * filename,int lineno)139 void *malloc_2(size_t size
140 #ifdef DEBUG_MALLOC_LINES
141 , char *filename, int lineno
142 #endif
143 )
144 {
145 void *ret;
146 
147 ret=malloc(size + 2*sizeof(void *));
148 if(ret)
149 	{
150 	void **ret2 = (void **)ret;
151 	*(ret2+0) = NULL;
152 	*(ret2+1) = GLOBALS->alloc2_chain;
153 	if(GLOBALS->alloc2_chain)
154 		{
155 		*(GLOBALS->alloc2_chain+0) = ret2;
156 		}
157 	GLOBALS->alloc2_chain = ret2;
158 
159 	GLOBALS->outstanding++;
160 
161 	return((char *)ret + 2*sizeof(void *));
162 	}
163 	else
164 	{
165 #ifdef DEBUG_MALLOC_LINES
166         fprintf(stderr, "FATAL ERROR: malloc_2() Out of memory, sorry. ['%s', %d]\n", filename, lineno);
167 #else
168 	fprintf(stderr, "FATAL ERROR: malloc_2() Out of memory, sorry.\n");
169 #endif
170 	exit(1);
171 	}
172 }
173 #endif
174 
175 #ifdef _WAVE_HAVE_JUDY
realloc_2(void * ptr,size_t size,char * filename,int lineno)176 void *realloc_2(void *ptr, size_t size
177 #ifdef DEBUG_MALLOC_LINES
178 , char *filename, int lineno
179 #endif
180 )
181 {
182 void *ret=realloc(ptr, size);
183 
184 if(ret)
185         {
186 	if(ptr != ret)
187 		{
188 		Judy1Unset ((Pvoid_t)&GLOBALS->alloc2_chain, (Word_t)ptr, PJE0);
189 		Judy1Set ((Pvoid_t)&GLOBALS->alloc2_chain, (Word_t)ret, PJE0);
190 		}
191 
192         return(ret);
193         }
194         else
195         {
196 #ifdef DEBUG_MALLOC_LINES
197         fprintf(stderr, "FATAL ERROR: realloc_2() Out of memory, sorry. ['%s', %d]\n", filename, lineno);
198 #else
199         fprintf(stderr, "FATAL ERROR: realloc_2() Out of memory, sorry.\n");
200 #endif
201         exit(1);
202         }
203 }
204 #else
realloc_2(void * ptr,size_t size,char * filename,int lineno)205 void *realloc_2(void *ptr, size_t size
206 #ifdef DEBUG_MALLOC_LINES
207 , char *filename, int lineno
208 #endif
209 )
210 {
211 void *ret;
212 
213 void **ret2 = ((void **)ptr) - 2;
214 void **prv = (void **)*(ret2+0);
215 void **nxt = (void **)*(ret2+1);
216 
217 if(prv)
218 	{
219         *(prv+1) = nxt;
220         }
221         else
222         {
223         GLOBALS->alloc2_chain = nxt;
224         }
225 
226 if(nxt)
227 	{
228         *(nxt+0) = prv;
229         }
230 
231 ret=realloc((char *)ptr - 2*sizeof(void *), size + 2*sizeof(void *));
232 
233 ret2 = (void **)ret;
234 *(ret2+0) = NULL;
235 *(ret2+1) = GLOBALS->alloc2_chain;
236 if(GLOBALS->alloc2_chain)
237 	{
238 	*(GLOBALS->alloc2_chain+0) = ret2;
239 	}
240 GLOBALS->alloc2_chain = ret2;
241 
242 if(ret)
243 	{
244 	return((char *)ret + 2*sizeof(void *));
245 	}
246 	else
247 	{
248 #ifdef DEBUG_MALLOC_LINES
249         fprintf(stderr, "FATAL ERROR: realloc_2() Out of memory, sorry. ['%s', %d]\n", filename, lineno);
250 #else
251 	fprintf(stderr, "FATAL ERROR: realloc_2() Out of memory, sorry.\n");
252 #endif
253 	exit(1);
254 	}
255 }
256 #endif
257 
258 #ifdef _WAVE_HAVE_JUDY
calloc_2_into_context(struct Global * g,size_t nmemb,size_t size,char * filename,int lineno)259 void *calloc_2_into_context(struct Global *g, size_t nmemb, size_t size
260 #ifdef DEBUG_MALLOC_LINES
261 , char *filename, int lineno
262 #endif
263 )
264 {
265 void *ret;
266 
267 ret=calloc(nmemb, size);
268 if(ret)
269 	{
270 	Judy1Set ((Pvoid_t)&g->alloc2_chain, (Word_t)ret, PJE0);
271 
272 	g->outstanding++;
273 
274 	return(ret);
275 	}
276 	else
277 	{
278 #ifdef DEBUG_MALLOC_LINES
279 	fprintf(stderr, "FATAL ERROR: calloc_2() Out of memory, sorry. ['%s', %d]\n", filename, lineno);
280 #else
281 	fprintf(stderr, "FATAL ERROR: calloc_2() Out of memory, sorry.\n");
282 #endif
283 	exit(1);
284 	}
285 }
286 #else
calloc_2_into_context(struct Global * g,size_t nmemb,size_t size,char * filename,int lineno)287 void *calloc_2_into_context(struct Global *g, size_t nmemb, size_t size
288 #ifdef DEBUG_MALLOC_LINES
289 , char *filename, int lineno
290 #endif
291 )
292 {
293 void *ret;
294 
295 ret=calloc(1, (nmemb * size) + 2*sizeof(void *));
296 if(ret)
297 	{
298 	void **ret2 = (void **)ret;
299 	*(ret2+0) = NULL;
300 	*(ret2+1) = g->alloc2_chain;
301 	if(g->alloc2_chain)
302 		{
303 		*(g->alloc2_chain+0) = ret2;
304 		}
305 	g->alloc2_chain = ret2;
306 
307 	g->outstanding++;
308 
309 	return((char *)ret + 2*sizeof(void *));
310 	}
311 	else
312 	{
313 #ifdef DEBUG_MALLOC_LINES
314         fprintf(stderr, "FATAL ERROR: calloc_2() Out of memory, sorry. ['%s', %d]\n", filename, lineno);
315 #else
316 	fprintf(stderr, "FATAL ERROR: calloc_2() Out of memory, sorry.\n");
317 #endif
318 	exit(1);
319 	}
320 }
321 #endif
322 
calloc_2(size_t nmemb,size_t size,char * filename,int lineno)323 void *calloc_2(size_t nmemb, size_t size
324 #ifdef DEBUG_MALLOC_LINES
325 , char *filename, int lineno
326 #endif
327 )
328 {
329 return(calloc_2_into_context(GLOBALS, nmemb, size
330 #ifdef DEBUG_MALLOC_LINES
331 , filename, lineno
332 #endif
333 ));
334 }
335 
336 
337 #ifdef _WAVE_HAVE_JUDY
free_2(void * ptr,char * filename,int lineno)338 void free_2(void *ptr
339 #ifdef DEBUG_MALLOC_LINES
340 , char *filename, int lineno
341 #endif
342 )
343 {
344 if(ptr)
345 	{
346 	int delstat = Judy1Unset ((Pvoid_t)&GLOBALS->alloc2_chain, (Word_t)ptr, PJE0);
347 
348 	if(delstat)
349 		{
350 		GLOBALS->outstanding--;
351 		free(ptr);
352 		}
353 		else
354 		{
355 #ifdef DEBUG_MALLOC_LINES
356 		printf("JUDYMEM | free to non-malloc'd address %p blocked ['%s', %d]\n", ptr, filename, lineno);
357 #else
358 		printf("JUDYMEM | free to non-malloc'd address %p blocked\n", ptr);
359 #endif
360 		}
361 	}
362 	else
363 	{
364 #ifdef DEBUG_MALLOC_LINES
365         fprintf(stderr, "WARNING: Attempt to free NULL pointer caught. ['%s', %d]\n", filename, lineno);
366 #else
367 	fprintf(stderr, "WARNING: Attempt to free NULL pointer caught.\n");
368 #endif
369 	}
370 }
371 #else
free_2(void * ptr,char * filename,int lineno)372 void free_2(void *ptr
373 #ifdef DEBUG_MALLOC_LINES
374 , char *filename, int lineno
375 #endif
376 )
377 {
378 if(ptr)
379 	{
380 	void **ret2 = ((void **)ptr) - 2;
381 	void **prv = (void **)*(ret2+0);
382 	void **nxt = (void **)*(ret2+1);
383 
384 	if(prv)
385 		{
386 		*(prv+1) = nxt;
387 		}
388 		else
389 		{
390 		GLOBALS->alloc2_chain = nxt;
391 		}
392 
393 	if(nxt)
394 		{
395 		*(nxt+0) = prv;
396 		}
397 
398 	GLOBALS->outstanding--;
399 
400 	free((char *)ptr - 2*sizeof(void *));
401 	}
402 	else
403 	{
404 #ifdef DEBUG_MALLOC_LINES
405         fprintf(stderr, "WARNING: Attempt to free NULL pointer caught. ['%s', %d]\n", filename, lineno);
406 #else
407 	fprintf(stderr, "WARNING: Attempt to free NULL pointer caught.\n");
408 #endif
409 	}
410 }
411 #endif
412 
413 
414 #ifdef DEBUG_MALLOC_LINES
415 #define malloc_2(x) malloc_2((x),__FILE__,__LINE__)
416 #endif
417 
418 
strdup_2(const char * s)419 char *strdup_2(const char *s)
420 {
421 char *s2 = NULL;
422 
423 if(s)
424 	{
425 	int nbytes = strlen(s) + 1;
426 	s2 = malloc_2(nbytes);
427 	memcpy(s2, s, nbytes);
428 	}
429 
430 return(s2);
431 }
432 
strdup_2s(const char * s)433 char *strdup_2s(const char *s)
434 {
435 char *s2 = NULL;
436 
437 if(s)
438 	{
439         int len = strlen(s);
440         s2 = malloc(len+2);
441         memcpy(s2, s, len);
442         s2[len++] = ' ';
443         s2[len] = 0;
444 	}
445 
446 return(s2);
447 }
448 
449 
450 /*
451  * atoi 64-bit version..
452  * y/on     default to '1'
453  * n/nonnum default to '0'
454  */
atoi_64(const char * str)455 TimeType atoi_64(const char *str)
456 {
457 TimeType val=0;
458 unsigned char ch, nflag=0;
459 int consumed = 0;
460 
461 GLOBALS->atoi_cont_ptr=NULL;
462 
463 switch(*str)
464 	{
465 	case 'y':
466 	case 'Y':
467 		return(LLDescriptor(1));
468 
469 	case 'o':
470 	case 'O':
471 		str++;
472 		ch=*str;
473 		if((ch=='n')||(ch=='N'))
474 			return(LLDescriptor(1));
475 		else	return(LLDescriptor(0));
476 
477 	case 'n':
478 	case 'N':
479 		return(LLDescriptor(0));
480 		break;
481 
482 	default:
483 		break;
484 	}
485 
486 while((ch=*(str++)))
487 	{
488 	if((ch>='0')&&(ch<='9'))
489 		{
490 		val=(val*10+(ch&15));
491 		consumed = 1;
492 		}
493 	else
494 	if((ch=='-')&&(val==0)&&(!nflag))
495 		{
496 		nflag=1;
497 		consumed = 1;
498 		}
499 	else
500 	if(consumed)
501 		{
502 		GLOBALS->atoi_cont_ptr=str-1;
503 		break;
504 		}
505 	}
506 return(nflag?(-val):val);
507 }
508 
509 
510 /*
511  * wrapped tooltips
512  */
gtk_tooltips_set_tip_2(GtkTooltips * tooltips,GtkWidget * widget,const gchar * tip_text,const gchar * tip_private)513 void gtk_tooltips_set_tip_2(GtkTooltips *tooltips, GtkWidget *widget,
514 	const gchar *tip_text, const gchar *tip_private)
515 {
516 if(!GLOBALS->disable_tooltips)
517 	{
518 	gtk_tooltips_set_tip(tooltips, widget, tip_text, tip_private);
519 	}
520 }
521 
522 
gtk_tooltips_set_delay_2(GtkTooltips * tooltips,guint delay)523 void gtk_tooltips_set_delay_2(GtkTooltips *tooltips, guint delay)
524 {
525 if(!GLOBALS->disable_tooltips)
526 	{
527 	gtk_tooltips_set_delay(tooltips, delay);
528 	}
529 }
530 
531 
gtk_tooltips_new_2(void)532 GtkTooltips* gtk_tooltips_new_2(void)
533 {
534 if(!GLOBALS->disable_tooltips)
535 	{
536 	return(gtk_tooltips_new());
537 	}
538 	else
539 	{
540 	return(NULL);
541 	}
542 }
543 
544 
tmpnam_2(char * s,int * fd)545 char *tmpnam_2(char *s, int *fd)
546 {
547 (void)s;
548 
549 #if defined _MSC_VER || defined __MINGW32__
550 char *fname = NULL;
551 TCHAR szTempFileName[MAX_PATH];
552 TCHAR lpTempPathBuffer[MAX_PATH];
553 DWORD dwRetVal = 0;
554 UINT uRetVal = 0;
555 
556 *fd = -1;
557 
558 dwRetVal = GetTempPath(MAX_PATH, lpTempPathBuffer);
559 if((dwRetVal > MAX_PATH) || (dwRetVal == 0))
560     	{
561 	fprintf(stderr, "GetTempPath() failed\n");
562     	}
563 	else
564 	{
565 	uRetVal = GetTempFileName(lpTempPathBuffer, TEXT("GTKW"), 0, szTempFileName);
566     	if (uRetVal == 0)
567     		{
568         	fprintf(stderr, "GetTempFileName() failed\n");
569 		}
570 		else
571 		{
572 		fname = strdup_2(szTempFileName);
573 		}
574 	}
575 
576 return(fname);
577 
578 #else
579 
580 char *backpath = "gtkwaveXXXXXX";
581 char *tmpspace;
582 int len = strlen(P_tmpdir);
583 int i;
584 
585 unsigned char slash = '/';
586 for(i=0;i<len;i++)
587 	{
588 	if((P_tmpdir[i] == '\\') || (P_tmpdir[i] == '/'))
589 		{
590 		slash = P_tmpdir[i];
591 		break;
592 		}
593 	}
594 
595 tmpspace = malloc_2(len + 1 + strlen(backpath) + 1);
596 sprintf(tmpspace, "%s%c%s", P_tmpdir, slash, backpath);
597 *fd = mkstemp(tmpspace);
598 if(*fd<0)
599 	{
600 	fprintf(stderr, "tmpnam_2() could not create tempfile, exiting.\n");
601 	perror("Why");
602 	exit(255);
603 	}
604 
605 return(tmpspace);
606 
607 #endif
608 }
609 
610 
wave_gtk_window_set_title(GtkWindow * window,const gchar * title,int typ,int pct)611 void wave_gtk_window_set_title(GtkWindow *window, const gchar *title, int typ, int pct)
612 {
613 if(window && title)
614 	{
615 	switch(typ)
616 		{
617 		case WAVE_SET_TITLE_MODIFIED:
618 			{
619 			const char *pfx = "[Modified] ";
620 			char *t = wave_alloca(strlen(pfx) + strlen(title) + 1);
621 
622 			strcpy(t, pfx);
623 			strcat(t, title);
624 			gtk_window_set_title(window, t);
625 			}
626 			break;
627 
628 		case WAVE_SET_TITLE_LOADING:
629 			{
630 			char *t = wave_alloca(64 + strlen(title) + 1); /* make extra long */
631 
632 			sprintf(t, "[Loading %d%%] %s", pct, title);
633 			gtk_window_set_title(window, t);
634 			}
635 			break;
636 
637 		case WAVE_SET_TITLE_NONE:
638 		default:
639 			gtk_window_set_title(window, title);
640 			break;
641 		}
642 	}
643 }
644 
645 
646 
realpath_2(const char * path,char * resolved_path)647 char *realpath_2(const char *path, char *resolved_path)
648 {
649 #if defined __USE_BSD || defined __USE_XOPEN_EXTENDED || defined __CYGWIN__ || defined HAVE_REALPATH
650 
651 #if (defined(__MACH__) && defined(__APPLE__))
652 if(!resolved_path)
653 	{
654 	resolved_path = malloc(PATH_MAX+1); /* fixes bug on Leopard when resolved_path == NULL */
655 	}
656 #endif
657 
658 return(realpath(path, resolved_path));
659 
660 #else
661 #ifdef __MINGW32__
662 if(!resolved_path)
663 	{
664 	resolved_path = malloc(PATH_MAX+1);
665 	}
666 return(_fullpath(resolved_path, path, PATH_MAX));
667 #else
668 return(NULL);
669 #endif
670 #endif
671 }
672 
673 
674 /******************************************************/
675 
676 #ifdef HAVE_SYS_STAT_H
677 
determine_gtkwave_filetype(const char * path)678 int determine_gtkwave_filetype(const char *path)
679 {
680 struct stat buf;
681 int rc = G_FT_UNKNOWN;
682 
683 #ifdef EXTLOAD_SUFFIX
684 if(suffix_check(GLOBALS->loaded_file_name, "."EXTLOAD_SUFFIX))
685 	{
686 	return(rc);
687 	}
688 #endif
689 
690 #ifdef AET2_IS_PRESENT
691 if(suffix_check(GLOBALS->loaded_file_name, ".aet") || suffix_check(GLOBALS->loaded_file_name, ".ae2"))
692 	{
693 	return(rc);
694 	}
695 #endif
696 
697 memset(&buf, 0, sizeof(struct stat));
698 if(stat(path, &buf) == 0)
699 	{
700 	if(S_ISREG(buf.st_mode))
701 		{
702 		FILE *f = fopen(path, "rb");
703 		if(f)
704 			{
705 			int hdr[2] = { 0, 0 };
706 			unsigned int magic_word;
707 
708 			hdr[0] = fgetc(f);
709 			hdr[1] = fgetc(f);
710 
711 			if((hdr[0] != EOF) && (hdr[1] != EOF))
712 				{
713 				magic_word = (hdr[0] * 256) + hdr[1];
714 
715 				switch(magic_word)
716 					{
717 					case LT_HDRID:		rc = G_FT_LXT; break;
718 					case LXT2_RD_HDRID:	rc = G_FT_LXT2; break;
719 					case VZT_RD_HDRID:	rc = G_FT_VZT; break;
720 					default: 		break;
721 					}
722 
723 				if(rc == G_FT_UNKNOWN)
724 					{
725 					if(hdr[0] == FST_BL_ZWRAPPER)
726 						{
727 						rc = G_FT_FST;
728 						}
729 					else if(hdr[0] == FST_BL_HDR)
730 						{
731 						unsigned char e_ch[8];
732 						int i, c;
733 						double fst_real_test = (2.7182818284590452354);
734 						int nfa, nfb;
735 
736 						for(i=0;i<23;i++)
737 							{
738 							if(fgetc(f) == EOF) goto chk_ex;
739 							}
740 
741 
742 						for(i=0;i<8;i++)
743 							{
744 							e_ch[i] = c = fgetc(f);
745 							if(c == EOF) goto chk_ex;
746 							}
747 
748 						nfa = nfb = 0;
749 						for(i=0;i<8;i++)
750 							{
751 							if(e_ch[i] == ((unsigned char *)&fst_real_test)[i])
752 								{
753 								nfa++;
754 								}
755 							if(e_ch[7-i] == ((unsigned char *)&fst_real_test)[i])
756 								{
757 								nfb++;
758 								}
759 							}
760 
761 						if((nfa == 8) || (nfb == 8))
762 							{
763 							rc = G_FT_FST;
764 							}
765 						}
766 					}
767 
768 				}
769 
770 chk_ex:			fclose(f);
771 			}
772 		}
773 	}
774 
775 errno = 0;
776 return(rc);
777 }
778 
779 #else
780 
determine_gtkwave_filetype(const char * path)781 int determine_gtkwave_filetype(const char *path)
782 {
783 return(G_FT_UNKNOWN);
784 }
785 
786 #endif
787 
788 /******************************************************/
789