ncurses 6.1 - patch 20191221
[ncurses.git] / test / tracemunch
1 #!/usr/bin/env perl
2 # $Id: tracemunch,v 1.26 2019/12/21 22:33:35 tom Exp $
3 ##############################################################################
4 # Copyright (c) 1998-2018,2019 Free Software Foundation, Inc.                #
5 #                                                                            #
6 # Permission is hereby granted, free of charge, to any person obtaining a    #
7 # copy of this software and associated documentation files (the "Software"), #
8 # to deal in the Software without restriction, including without limitation  #
9 # the rights to use, copy, modify, merge, publish, distribute, distribute    #
10 # with modifications, sublicense, and/or sell copies of the Software, and to #
11 # permit persons to whom the Software is furnished to do so, subject to the  #
12 # following conditions:                                                      #
13 #                                                                            #
14 # The above copyright notice and this permission notice shall be included in #
15 # all copies or substantial portions of the Software.                        #
16 #                                                                            #
17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR #
18 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,   #
19 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    #
20 # THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER      #
21 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING    #
22 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER        #
23 # DEALINGS IN THE SOFTWARE.                                                  #
24 #                                                                            #
25 # Except as contained in this notice, the name(s) of the above copyright     #
26 # holders shall not be used in advertising or otherwise to promote the sale, #
27 # use or other dealings in this Software without prior written               #
28 # authorization.                                                             #
29 ##############################################################################
30 # tracemunch -- compactify ncurses trace logs
31 #
32 # The error logs produced by ncurses with tracing enabled can be very tedious
33 # to wade through.  This script helps by compacting runs of log lines that
34 # can be conveniently expressed as higher-level operations.
35
36 use strict;
37 use warnings;
38
39 our $putattr =
40     'PutAttrChar\(\{\{ ' . "'(.)'"
41   . ' = 0[0-7]+ \}\}\) at \(([0-9]+), ([0-9]+)\)';
42 our $waddnstr =
43   'waddnstr\(0x([[:xdigit:]]+),"([^\"]+)",[0-9]+\) called \{A_NORMAL\}';
44
45 # If the trace is complete, we can infer addresses using the return value from
46 # newwin, etc.  But if it is incomplete, we can still check for special cases
47 # such as SCREEN* and WINDOW* parameters.  In this table, the type for the
48 # first parameter is encoded, relying upon an ncurses programming convention:
49 # 1 = SCREEN*
50 # 2 = WINDOW*
51 # 4 = TERMINAL*
52 our %known_p1 = qw(
53   TransformLine           1
54   _nc_freewin             2
55   _nc_initscr             1
56   _nc_makenew             1
57   _nc_mingw_console_read  1
58   _nc_reset_colors        1
59   _nc_scroll_optimize     1
60   _nc_tinfo               1
61   _nc_tinfo_mvcur         1
62   _nc_wgetch              2
63   adjust_window           2
64   assume_default_colors   1
65   attr_get                2
66   baudrate                1
67   beep                    1
68   border_set              2
69   box                     2
70   box_set                 2
71   can_change_color        1
72   cbreak                  1
73   clearok                 2
74   color_content           1
75   copywin                 2
76   curs_set                1
77   decrease_size           1
78   def_prog_mode           1
79   def_shell_mode          1
80   define_key              1
81   del_curterm             1
82   delay_output            1
83   delscreen               1
84   delwin                  2
85   derwin                  2
86   doupdate                1
87   dupwin                  2
88   echo                    1
89   endwin                  1
90   erasechar               1
91   filter                  1
92   flash                   1
93   flushinp                1
94   getattrs                2
95   getbegx                 2
96   getbegy                 2
97   getbkgd                 2
98   getcurx                 2
99   getcury                 2
100   getmaxx                 2
101   getmaxy                 2
102   getmouse                1
103   getparx                 2
104   getpary                 2
105   halfdelay               1
106   has_ic                  1
107   has_il                  1
108   has_key                 1
109   idcok                   2
110   idlok                   2
111   immedok                 2
112   increase_size           1
113   init_color              1
114   init_pair               1
115   intrflush               1
116   is_cleared              2
117   is_idcok                2
118   is_idlok                2
119   is_immedok              2
120   is_keypad               2
121   is_leaveok              2
122   is_linetouched          2
123   is_nodelay              2
124   is_notimeout            2
125   is_pad                  2
126   is_scrollok             2
127   is_subwin               2
128   is_syncok               2
129   is_term_resized         1
130   is_wintouched           2
131   key_defined             1
132   keybound                1
133   keyok                   1
134   keypad                  2
135   killchar                1
136   leaveok                 2
137   longname                1
138   meta                    2
139   mouseinterval           1
140   mousemask               1
141   mvcur                   1
142   mvderwin                2
143   mvwadd_wch              2
144   mvwadd_wchnstr          2
145   mvwadd_wchstr           2
146   mvwaddch                2
147   mvwaddchnstr            2
148   mvwaddchstr             2
149   mvwaddnstr              2
150   mvwaddnwstr             2
151   mvwaddstr               2
152   mvwaddwstr              2
153   mvwchgat                2
154   mvwdelch                2
155   mvwget_wch              2
156   mvwget_wstr             2
157   mvwgetch                2
158   mvwgetn_wstr            2
159   mvwgetnstr              2
160   mvwgetstr               2
161   mvwhline                2
162   mvwhline_set            2
163   mvwin                   2
164   mvwin_wch               2
165   mvwin_wchnstr           2
166   mvwin_wchstr            2
167   mvwinch                 2
168   mvwinchnstr             2
169   mvwinchstr              2
170   mvwins_nwstr            2
171   mvwins_wch              2
172   mvwins_wstr             2
173   mvwinsch                2
174   mvwinsnstr              2
175   mvwinsstr               2
176   mvwinstr                2
177   mvwinwstr               2
178   mvwvline                2
179   mvwvline_set            2
180   newpad                  1
181   newterm                 1
182   newwin                  1
183   nl                      1
184   nocbreak                1
185   nodelay                 2
186   noecho                  1
187   nofilter                1
188   nonl                    1
189   noqiflush               1
190   noraw                   1
191   notimeout               2
192   overlap                 2
193   overlay                 2
194   overwrite               2
195   pair_content            1
196   pecho_wchar             2
197   pechochar               2
198   pnoutrefresh            2
199   putwin                  2
200   qiflush                 1
201   raw                     1
202   redrawwin               2
203   reset_prog_mode         1
204   reset_shell_mode        1
205   resetty                 1
206   resize_term             1
207   resizeterm              1
208   restartterm             1
209   ripoffline              1
210   savetty                 1
211   scr_init                1
212   scr_restore             1
213   scr_set                 1
214   scroll                  2
215   scrollok                2
216   set_curterm             4
217   set_term                1
218   slk_attr                1
219   slk_attr_set            1
220   slk_attroff             1
221   slk_attron              1
222   slk_attrset             1
223   slk_clear               1
224   slk_color               1
225   slk_init                1
226   slk_label               1
227   slk_noutrefresh         1
228   slk_refresh             1
229   slk_restore             1
230   slk_set                 1
231   slk_touch               1
232   start_color             1
233   subwin                  2
234   syncok                  2
235   termattrs               1
236   termname                1
237   tgetflag                1
238   tgetnum                 1
239   tigetflag               1
240   tigetnum                1
241   tigetstr                1
242   tinfo                   1
243   touchline               2
244   touchwin                2
245   typeahead               1
246   unget_wch               1
247   ungetch                 1
248   ungetmouse              1
249   untouchwin              2
250   use_default_colors      1
251   use_env                 1
252   use_legacy_coding       1
253   use_screen              1
254   use_tioctl              1
255   use_window              2
256   vidattr                 1
257   vidputs                 1
258   vw_printw               2
259   vwprintw                2
260   wadd_wch                2
261   wadd_wchnstr            2
262   wadd_wchstr             2
263   waddch                  2
264   waddchnstr              2
265   waddchstr               2
266   waddnstr                2
267   waddnwstr               2
268   waddstr                 2
269   waddwstr                2
270   wattr_get               2
271   wattr_off               2
272   wattr_on                2
273   wattr_set               2
274   wattroff                2
275   wattron                 2
276   wattrset                2
277   wbkgd                   2
278   wbkgdset                2
279   wborder                 2
280   wborder_set             2
281   wchgat                  2
282   wclear                  2
283   wclrtobot               2
284   wclrtoeol               2
285   wcolor_set              2
286   wcursyncup              2
287   wdelch                  2
288   wdeleteln               2
289   wechochar               2
290   wenclose                2
291   werase                  2
292   wget_wch                2
293   wget_wstr               2
294   wgetbkgrnd              2
295   wgetch                  2
296   wgetch_events           2
297   wgetdelay               2
298   wgetn_wstr              2
299   wgetnstr                2
300   wgetparent              2
301   wgetscrreg              2
302   wgetstr                 2
303   whline                  2
304   whline_set              2
305   win_wch                 2
306   win_wchnstr             2
307   win_wchstr              2
308   winch                   2
309   winchnstr               2
310   winchstr                2
311   winnstr                 2
312   winnwstr                2
313   wins_nwstr              2
314   wins_wch                2
315   wins_wstr               2
316   winsch                  2
317   winsdelln               2
318   winsertln               2
319   winsnstr                2
320   winsstr                 2
321   winstr                  2
322   winwstr                 2
323   wmouse_trafo            2
324   wmove                   2
325   wnoutrefresh            2
326   wprintw                 2
327   wredrawln               2
328   wrefresh                2
329   wresize                 2
330   wscrl                   2
331   wsetscrreg              2
332   wstandend               2
333   wstandout               2
334   wsyncdown               2
335   wsyncup                 2
336   wtimeout                2
337   wtouchln                2
338   wvline                  2
339 );
340
341 our $scr_nums = 0;
342 our $thr_nums = 0;
343 our $trm_nums = 0;
344 our $try_nums = 0;
345 our $win_nums = 0;
346 our $curscr   = "";
347 our $newscr   = "";
348 our $stdscr   = "";
349 our %scr_addr;
350 our %thr_addr;
351 our %trm_addr;
352 our %try_addr;
353 our %win_addr;
354
355 sub has_addr($) {
356     my $value  = shift;
357     my $result = 0;
358     $result = 1 if ( $value =~ /\b0x[[:xdigit:]]+\b/i );
359     return $result;
360 }
361
362 sub transaddr($) {
363     my $arg = shift;
364     my $n;
365
366     $arg =~ s/\b$curscr\b/curscr/g if ($curscr);
367     $arg =~ s/\b$newscr\b/newscr/g if ($newscr);
368     $arg =~ s/\b$stdscr\b/stdscr/g if ($stdscr);
369     if ( &has_addr($arg) ) {
370         foreach my $addr ( keys %scr_addr ) {
371             $n = $scr_addr{$addr};
372             $arg =~ s/\b$addr\b/screen$n/g if ( defined $n );
373         }
374     }
375     if ( &has_addr($arg) ) {
376         foreach my $addr ( keys %thr_addr ) {
377             $n = $thr_addr{$addr};
378             $arg =~ s/\b$addr\b/thread$n/g if ( defined $n );
379         }
380     }
381     if ( &has_addr($arg) ) {
382         foreach my $addr ( keys %trm_addr ) {
383             $n = $trm_addr{$addr};
384             $arg =~ s/\b$addr\b/terminal$n/g if ( defined $n );
385         }
386     }
387     if ( &has_addr($arg) ) {
388         foreach my $addr ( keys %try_addr ) {
389             $n = $try_addr{$addr};
390             $arg =~ s/\b$addr\b/tries_$n/g if ( defined $n );
391         }
392     }
393     if ( &has_addr($arg) ) {
394         foreach my $addr ( keys %win_addr ) {
395             $n = $win_addr{$addr};
396             $arg =~ s/\b$addr\b/window$n/g if ( defined $n );
397         }
398     }
399     if ( &has_addr($arg) ) {
400         if ( $arg =~ /add_wch\((window\d+,)?0x[[:xdigit:]]+\)/i ) {
401             $arg =~ s/(0x[[:xdigit:]]+)[)]/\&wch)/i;
402         }
403         elsif (
404             $arg =~ /color_content\((screen\d+,)?\d+(,0x[[:xdigit:]]+){3}/i )
405         {
406             $arg =~ s/(,0x[[:xdigit:]]+){3}[)]/,\&r,\&g,\&b)/i;
407         }
408         elsif ( $arg =~ /pair_content\((screen\d+,)?\d+(,0x[[:xdigit:]]+){2}/i )
409         {
410             $arg =~ s/(,0x[[:xdigit:]]+){2}[)]/,\&fg,\&bg)/i;
411         }
412     }
413     if ( &has_addr($arg) and $arg =~ /called\s+\{/ ) {
414         my $func = $arg;
415         chomp $func;
416         $func =~ s/^.*called\s+\{([[:alnum:]_]+)\(.*$/$1/;
417         if ( defined $known_p1{$func} ) {
418             my $addr = $arg;
419             my $type = $known_p1{$func};
420             chomp $addr;
421             $addr =~ s/^[^(]+\((0x[[:xdigit:]]+).*/$1/i;
422             if ( $type == 1 ) {
423                 $scr_addr{$addr} = ++$scr_nums;
424                 $arg = &transaddr($arg);
425             }
426             elsif ( $type == 2 ) {
427                 $win_addr{$addr} = ++$win_nums;
428                 $arg = &transaddr($arg);
429             }
430             elsif ( $type == 4 ) {
431                 $trm_addr{$addr} = ++$trm_nums;
432                 $arg = &transaddr($arg);
433             }
434         }
435     }
436
437     return $arg;
438 }
439
440 sub muncher($) {
441     my $STDIN = shift;
442
443     while (<$STDIN>) {
444         my $addr;
445         my $n;
446         my $awaiting = "";
447
448       CLASSIFY: {
449
450             # just in case someone tries a file with cr/lf line-endings:
451             $_ =~ s/\r\n/\n/g;
452             $_ =~ s/\r/\n/g;
453
454             my $thread = "";
455             if ( $_ =~ /^(0x[[:xdigit:]]+):/ ) {
456                 $thr_addr{$1} = ++$thr_nums unless defined $thr_addr{$1};
457                 $thread = "thread" . $thr_addr{$1} . ":";
458                 $_ =~ s/^[^:]*://;
459             }
460
461             # Transform window pointer addresses so it's easier to compare logs
462             $awaiting = "curscr" if ( $_ =~ /creating curscr/ );
463             $awaiting = "newscr" if ( $_ =~ /creating newscr/ );
464             $awaiting = "stdscr" if ( $_ =~ /creating stdscr/ );
465             $awaiting = "screen" if ( $_ =~ /^(\+ )*called \{new_prescr\(\)/ );
466             if ( $_ =~ /^create :window 0x([[:xdigit:]]+)/ ) {
467                 $addr = "0x$1";
468                 if ( $awaiting eq "curscr" ) {
469                     $curscr = $addr;
470                 }
471                 elsif ( $awaiting eq "newscr" ) {
472                     $newscr = $addr;
473                 }
474                 elsif ( $awaiting eq "stdscr" ) {
475                     $stdscr = $addr;
476                 }
477                 else {
478                     $win_addr{$addr} = $win_nums++;
479                 }
480                 $awaiting = "";
481             }
482             elsif ( $_ =~ /^(\+ )*called \{set_curterm\((0x[[:xdigit:]]+)\)/ ) {
483                 $trm_addr{$2} = ++$trm_nums unless defined $trm_addr{$2};
484             }
485             elsif ( $_ =~ /^(\+ )*called \{_nc_add_to_try\((0x[[:xdigit:]]+),/ )
486             {
487                 $try_addr{$2} = ++$try_nums unless defined $try_addr{$2};
488             }
489             elsif ( $_ =~ /^(\+ )*_nc_alloc_screen_sp 0x([[:xdigit:]]+)/ ) {
490                 $addr = "0x$2";
491                 $scr_addr{$addr} = ++$scr_nums unless ( $scr_addr{$addr} );
492                 $awaiting = "";
493             }
494             elsif ( $_ =~ /^(\+ )*return }0x([[:xdigit:]]+)/ ) {
495                 $addr = "0x$2";
496                 if ( $awaiting eq "screen" ) {
497                     $scr_addr{$addr} = ++$scr_nums unless ( $scr_addr{$addr} );
498                 }
499             }
500             elsif ( $_ =~ /^\.\.\.deleted win=0x([[:xdigit:]]+)/ ) {
501                 $addr = "0x$1";
502                 $_    = &transaddr($_);
503                 if ( $addr eq $curscr ) {
504                     $curscr = "";
505                 }
506                 elsif ( $addr eq $newscr ) {
507                     $newscr = "";
508                 }
509                 elsif ( $addr eq $stdscr ) {
510                     $stdscr = "";
511                 }
512                 else {
513                     undef $win_addr{$addr};
514                 }
515             }
516
517             # Compactify runs of PutAttrChar calls (TR_CHARPUT)
518             if ( $_ =~ /$putattr/ ) {
519                 my $putattr_chars = $1;
520                 my $starty        = $2;
521                 my $startx        = $3;
522                 while (<$STDIN>) {
523                     if ( $_ =~ /$putattr/ ) {
524                         $putattr_chars .= $1;
525                     }
526                     else {
527                         last;
528                     }
529                 }
530                 print
531 "RUN of PutAttrChar()s: \"$putattr_chars\" from ${starty}, ${startx}\n";
532                 redo CLASSIFY;
533             }
534
535             # Compactify runs of waddnstr calls (TR_CALLS)
536             if ( $_ =~ /$waddnstr/ ) {
537                 my $waddnstr_chars = $2;
538                 my $winaddr        = $1;
539                 while (<$STDIN>) {
540                     if ( $_ =~ /$waddnstr/ && $1 eq $winaddr ) {
541                         $waddnstr_chars .= $2;
542                     }
543                     else {
544                         last;
545                     }
546                 }
547                 my $winaddstr = &transaddr($winaddr);
548                 print "RUN of waddnstr()s: $winaddr, \"$waddnstr_chars\"\n";
549                 redo CLASSIFY;
550             }
551
552             # More transformations can go here
553
554             # Repeated runs of anything
555             my $anyline     = &transaddr($_);
556             my $repeatcount = 1;
557             while (<$STDIN>) {
558                 if ( &transaddr($_) eq $anyline ) {
559                     $repeatcount++;
560                 }
561                 else {
562                     last;
563                 }
564             }
565             if ( $repeatcount > 1 ) {
566                 print "${repeatcount} REPEATS OF $anyline";
567             }
568             else {
569                 print $thread . $anyline;
570             }
571             redo CLASSIFY if $_;
572
573         }    # :CLASSIFY
574     }
575 }
576
577 if ( $#ARGV >= 0 ) {
578     while ( $#ARGV >= 0 ) {
579         my $file = shift @ARGV;
580         open my $ifh, "<", $file or die $!;
581         &muncher($ifh);
582     }
583 }
584 else {
585     &muncher( \*STDIN );
586 }
587
588 # tracemunch ends here