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