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