ncurses 6.2 - patch 20210220
[ncurses.git] / test / tracemunch
1 #!/usr/bin/env perl
2 # $Id: tracemunch,v 1.40 2021/02/13 19:29:12 tom Exp $
3 ##############################################################################
4 # Copyright 2018-2020,2021 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 '^called \{waddnstr\((0x[[:xdigit:]]+|window\d+),"((\\.|[^\"]*))",[-]?[0-9]+\)';
47
48 our %TR = qw(
49   DISABLE       0x0000
50   TIMES         0x0001
51   TPUTS         0x0002
52   UPDATE        0x0004
53   MOVE          0x0008
54   CHARPUT       0x0010
55   ORDINARY      0x001F
56   CALLS         0x0020
57   VIRTPUT       0x0040
58   IEVENT        0x0080
59   BITS          0x0100
60   ICALLS        0x0200
61   CCALLS        0x0400
62   DATABASE      0x0800
63   ATTRS         0x1000
64 );
65
66 our $tracelevel = 0;
67
68 our $tSCREEN   = 1;    # SCREEN*
69 our $tWINDOW   = 2;    # WINDOW*
70 our $tTERMINAL = 3;    # TERMINAL*
71 our $tPANEL    = 4;    # PANEL*
72 our $tFIELD    = 5;    # FIELD*
73 our $tFORM     = 5;    # FORM*
74 our $tMENU     = 6;    # MENU*
75 our $tITEM     = 7;    # ITEM*
76
77 our %known_p1_types = (
78     $tSCREEN   => "SCREEN*",
79     $tWINDOW   => "WINDOW*",
80     $tTERMINAL => "TERMINAL*",
81     $tPANEL    => "PANEL*",
82     $tFORM     => "FORM*",
83     $tFIELD    => "FIELD*",
84     $tMENU     => "MENU*",
85     $tITEM     => "ITEM*",
86 );
87
88 # If the trace is complete, we can infer addresses using the return value from
89 # newwin, etc.  But if it is incomplete, we can still check for special cases
90 # such as SCREEN* and WINDOW* parameters.  In this table, the type for the
91 # first parameter is encoded, relying upon an ncurses programming convention:
92 our %known_p1 = (
93     TransformLine          => $tSCREEN,
94     _nc_console_read       => $tSCREEN,
95     _nc_freewin            => $tWINDOW,
96     _nc_initscr            => $tSCREEN,
97     _nc_makenew            => $tSCREEN,
98     _nc_mingw_console_read => $tSCREEN,
99     _nc_reset_colors       => $tSCREEN,
100     _nc_scroll_optimize    => $tSCREEN,
101     _nc_tinfo              => $tSCREEN,
102     _nc_tinfo_mvcur        => $tSCREEN,
103     _nc_wgetch             => $tWINDOW,
104     adjust_window          => $tWINDOW,
105     assume_default_colors  => $tSCREEN,
106     attr_get               => $tWINDOW,
107     baudrate               => $tSCREEN,
108     beep                   => $tSCREEN,
109     border_set             => $tWINDOW,
110     bottom_panel           => $tPANEL,
111     bottom_panel           => $tPANEL,
112     box                    => $tWINDOW,
113     box_set                => $tWINDOW,
114     can_change_color       => $tSCREEN,
115     cbreak                 => $tSCREEN,
116     ceiling_panel          => $tSCREEN,
117     clearok                => $tWINDOW,
118     color_content          => $tSCREEN,
119     copywin                => $tWINDOW,
120     current_item           => $tMENU,
121     curs_set               => $tSCREEN,
122     decrease_size          => $tSCREEN,
123     def_prog_mode          => $tSCREEN,
124     def_shell_mode         => $tSCREEN,
125     define_key             => $tSCREEN,
126     del_curterm            => $tSCREEN,
127     del_panel              => $tPANEL,
128     del_panel              => $tPANEL,
129     delay_output           => $tSCREEN,
130     delscreen              => $tSCREEN,
131     delwin                 => $tWINDOW,
132     derwin                 => $tWINDOW,
133     doupdate               => $tSCREEN,
134     dup_field              => $tFIELD,
135     dupwin                 => $tWINDOW,
136     echo                   => $tSCREEN,
137     endwin                 => $tSCREEN,
138     erasechar              => $tSCREEN,
139     field_opts_off         => $tFIELD,
140     field_opts_on          => $tFIELD,
141     filter                 => $tSCREEN,
142     flash                  => $tSCREEN,
143     flushinp               => $tSCREEN,
144     form_driver            => $tFORM,
145     form_driver_w          => $tFORM,
146     form_opts_off          => $tFORM,
147     form_opts_on           => $tFORM,
148     free_field             => $tFIELD,
149     free_form              => $tFORM,
150     free_item              => $tITEM,
151     free_menu              => $tMENU,
152     getattrs               => $tWINDOW,
153     getbegx                => $tWINDOW,
154     getbegy                => $tWINDOW,
155     getbkgd                => $tWINDOW,
156     getcurx                => $tWINDOW,
157     getcury                => $tWINDOW,
158     getmaxx                => $tWINDOW,
159     getmaxy                => $tWINDOW,
160     getmouse               => $tSCREEN,
161     getparx                => $tWINDOW,
162     getpary                => $tWINDOW,
163     ground_panel           => $tSCREEN,
164     halfdelay              => $tSCREEN,
165     has_ic                 => $tSCREEN,
166     has_il                 => $tSCREEN,
167     has_key                => $tSCREEN,
168     hide_panel             => $tPANEL,
169     hide_panel             => $tPANEL,
170     idcok                  => $tWINDOW,
171     idlok                  => $tWINDOW,
172     immedok                => $tWINDOW,
173     increase_size          => $tSCREEN,
174     init_color             => $tSCREEN,
175     init_pair              => $tSCREEN,
176     intrflush              => $tSCREEN,
177     is_cleared             => $tWINDOW,
178     is_idcok               => $tWINDOW,
179     is_idlok               => $tWINDOW,
180     is_immedok             => $tWINDOW,
181     is_keypad              => $tWINDOW,
182     is_leaveok             => $tWINDOW,
183     is_linetouched         => $tWINDOW,
184     is_nodelay             => $tWINDOW,
185     is_notimeout           => $tWINDOW,
186     is_pad                 => $tWINDOW,
187     is_scrollok            => $tWINDOW,
188     is_subwin              => $tWINDOW,
189     is_syncok              => $tWINDOW,
190     is_term_resized        => $tSCREEN,
191     is_wintouched          => $tWINDOW,
192     item_count             => $tMENU,
193     item_description       => $tITEM,
194     item_index             => $tITEM,
195     item_init              => $tMENU,
196     item_name              => $tITEM,
197     item_opts              => $tITEM,
198     item_opts_off          => $tITEM,
199     item_opts_on           => $tITEM,
200     item_term              => $tMENU,
201     item_userptr           => $tITEM,
202     item_value             => $tITEM,
203     item_visible           => $tITEM,
204     key_defined            => $tSCREEN,
205     keybound               => $tSCREEN,
206     keyok                  => $tSCREEN,
207     keypad                 => $tWINDOW,
208     killchar               => $tSCREEN,
209     leaveok                => $tWINDOW,
210     link_field             => $tFIELD,
211     longname               => $tSCREEN,
212     menu_back              => $tMENU,
213     menu_driver            => $tMENU,
214     menu_fore              => $tMENU,
215     menu_format            => $tMENU,
216     menu_grey              => $tMENU,
217     menu_init              => $tMENU,
218     menu_items             => $tMENU,
219     menu_mark              => $tMENU,
220     menu_opts              => $tMENU,
221     menu_opts_off          => $tMENU,
222     menu_opts_on           => $tMENU,
223     menu_pad               => $tMENU,
224     menu_pattern           => $tMENU,
225     menu_spacing           => $tMENU,
226     menu_sub               => $tMENU,
227     menu_term              => $tMENU,
228     menu_userptr           => $tMENU,
229     menu_win               => $tMENU,
230     meta                   => $tWINDOW,
231     mouseinterval          => $tSCREEN,
232     mousemask              => $tSCREEN,
233     move_field             => $tFIELD,
234     move_panel             => $tPANEL,
235     move_panel             => $tPANEL,
236     mvcur                  => $tSCREEN,
237     mvderwin               => $tWINDOW,
238     mvwadd_wch             => $tWINDOW,
239     mvwadd_wchnstr         => $tWINDOW,
240     mvwadd_wchstr          => $tWINDOW,
241     mvwaddch               => $tWINDOW,
242     mvwaddchnstr           => $tWINDOW,
243     mvwaddchstr            => $tWINDOW,
244     mvwaddnstr             => $tWINDOW,
245     mvwaddnwstr            => $tWINDOW,
246     mvwaddstr              => $tWINDOW,
247     mvwaddwstr             => $tWINDOW,
248     mvwchgat               => $tWINDOW,
249     mvwdelch               => $tWINDOW,
250     mvwget_wch             => $tWINDOW,
251     mvwget_wstr            => $tWINDOW,
252     mvwgetch               => $tWINDOW,
253     mvwgetn_wstr           => $tWINDOW,
254     mvwgetnstr             => $tWINDOW,
255     mvwgetstr              => $tWINDOW,
256     mvwhline               => $tWINDOW,
257     mvwhline_set           => $tWINDOW,
258     mvwin                  => $tWINDOW,
259     mvwin_wch              => $tWINDOW,
260     mvwin_wchnstr          => $tWINDOW,
261     mvwin_wchstr           => $tWINDOW,
262     mvwinch                => $tWINDOW,
263     mvwinchnstr            => $tWINDOW,
264     mvwinchstr             => $tWINDOW,
265     mvwins_nwstr           => $tWINDOW,
266     mvwins_wch             => $tWINDOW,
267     mvwins_wstr            => $tWINDOW,
268     mvwinsch               => $tWINDOW,
269     mvwinsnstr             => $tWINDOW,
270     mvwinsstr              => $tWINDOW,
271     mvwinstr               => $tWINDOW,
272     mvwinwstr              => $tWINDOW,
273     mvwvline               => $tWINDOW,
274     mvwvline_set           => $tWINDOW,
275     new_panel              => $tWINDOW,
276     new_panel              => $tWINDOW,
277     newpad                 => $tSCREEN,
278     newterm                => $tSCREEN,
279     newwin                 => $tSCREEN,
280     nl                     => $tSCREEN,
281     nocbreak               => $tSCREEN,
282     nodelay                => $tWINDOW,
283     noecho                 => $tSCREEN,
284     nofilter               => $tSCREEN,
285     nonl                   => $tSCREEN,
286     noqiflush              => $tSCREEN,
287     noraw                  => $tSCREEN,
288     notimeout              => $tWINDOW,
289     overlap                => $tWINDOW,
290     overlay                => $tWINDOW,
291     overwrite              => $tWINDOW,
292     pair_content           => $tSCREEN,
293     panel_above            => $tPANEL,
294     panel_above            => $tPANEL,
295     panel_below            => $tPANEL,
296     panel_below            => $tPANEL,
297     panel_hidden           => $tPANEL,
298     panel_hidden           => $tPANEL,
299     panel_userptr          => $tPANEL,
300     panel_userptr          => $tPANEL,
301     panel_window           => $tPANEL,
302     panel_window           => $tPANEL,
303     pecho_wchar            => $tWINDOW,
304     pechochar              => $tWINDOW,
305     pnoutrefresh           => $tWINDOW,
306     pos_form_cursor        => $tFORM,
307     pos_menu_cursor        => $tMENU,
308     post_form              => $tFORM,
309     post_menu              => $tMENU,
310     putwin                 => $tWINDOW,
311     qiflush                => $tSCREEN,
312     raw                    => $tSCREEN,
313     redrawwin              => $tWINDOW,
314     replace_panel          => $tPANEL,
315     replace_panel          => $tPANEL,
316     reset_prog_mode        => $tSCREEN,
317     reset_shell_mode       => $tSCREEN,
318     resetty                => $tSCREEN,
319     resize_term            => $tSCREEN,
320     resizeterm             => $tSCREEN,
321     restartterm            => $tSCREEN,
322     ripoffline             => $tSCREEN,
323     savetty                => $tSCREEN,
324     scale_menu             => $tMENU,
325     scr_init               => $tSCREEN,
326     scr_restore            => $tSCREEN,
327     scr_set                => $tSCREEN,
328     scroll                 => $tWINDOW,
329     scrollok               => $tWINDOW,
330     set_current_field      => $tFORM,
331     set_current_item       => $tMENU,
332     set_curterm            => $tTERMINAL,
333     set_field_back         => $tFIELD,
334     set_field_buffer       => $tFIELD,
335     set_field_fore         => $tFIELD,
336     set_field_init         => $tFORM,
337     set_field_just         => $tFIELD,
338     set_field_opts         => $tFIELD,
339     set_field_pad          => $tFIELD,
340     set_field_status       => $tFIELD,
341     set_field_term         => $tFORM,
342     set_field_type         => $tFIELD,
343     set_field_userptr      => $tFIELD,
344     set_form_fields        => $tFORM,
345     set_form_init          => $tFORM,
346     set_form_opts          => $tFORM,
347     set_form_page          => $tFORM,
348     set_form_sub           => $tFORM,
349     set_form_term          => $tFORM,
350     set_form_userptr       => $tFORM,
351     set_form_win           => $tFORM,
352     set_item_init          => $tMENU,
353     set_item_opts          => $tITEM,
354     set_item_term          => $tMENU,
355     set_item_userptr       => $tITEM,
356     set_item_value         => $tITEM,
357     set_menu_back          => $tMENU,
358     set_menu_fore          => $tMENU,
359     set_menu_format        => $tMENU,
360     set_menu_grey          => $tMENU,
361     set_menu_init          => $tMENU,
362     set_menu_items         => $tMENU,
363     set_menu_mark          => $tMENU,
364     set_menu_opts          => $tMENU,
365     set_menu_pad           => $tMENU,
366     set_menu_pattern       => $tMENU,
367     set_menu_spacing       => $tMENU,
368     set_menu_sub           => $tMENU,
369     set_menu_term          => $tMENU,
370     set_menu_userptr       => $tMENU,
371     set_menu_win           => $tMENU,
372     set_new_page           => $tFIELD,
373     set_panel_userptr      => $tPANEL,
374     set_panel_userptr      => $tPANEL,
375     set_term               => $tSCREEN,
376     set_top_row            => $tMENU,
377     show_panel             => $tPANEL,
378     show_panel             => $tPANEL,
379     slk_attr               => $tSCREEN,
380     slk_attr_set           => $tSCREEN,
381     slk_attroff            => $tSCREEN,
382     slk_attron             => $tSCREEN,
383     slk_attrset            => $tSCREEN,
384     slk_clear              => $tSCREEN,
385     slk_color              => $tSCREEN,
386     slk_init               => $tSCREEN,
387     slk_label              => $tSCREEN,
388     slk_noutrefresh        => $tSCREEN,
389     slk_refresh            => $tSCREEN,
390     slk_restore            => $tSCREEN,
391     slk_set                => $tSCREEN,
392     slk_touch              => $tSCREEN,
393     start_color            => $tSCREEN,
394     subwin                 => $tWINDOW,
395     syncok                 => $tWINDOW,
396     termattrs              => $tSCREEN,
397     termname               => $tSCREEN,
398     tgetflag               => $tSCREEN,
399     tgetnum                => $tSCREEN,
400     tigetflag              => $tSCREEN,
401     tigetnum               => $tSCREEN,
402     tigetstr               => $tSCREEN,
403     tinfo                  => $tSCREEN,
404     top_panel              => $tPANEL,
405     top_panel              => $tPANEL,
406     top_row                => $tMENU,
407     touchline              => $tWINDOW,
408     touchwin               => $tWINDOW,
409     typeahead              => $tSCREEN,
410     unfocus_current_field  => $tFORM,
411     unget_wch              => $tSCREEN,
412     ungetch                => $tSCREEN,
413     ungetmouse             => $tSCREEN,
414     unpost_form            => $tFORM,
415     unpost_menu            => $tMENU,
416     untouchwin             => $tWINDOW,
417     update_panels_sp       => $tSCREEN,
418     use_default_colors     => $tSCREEN,
419     use_env                => $tSCREEN,
420     use_legacy_coding      => $tSCREEN,
421     use_screen             => $tSCREEN,
422     use_tioctl             => $tSCREEN,
423     use_window             => $tWINDOW,
424     vidattr                => $tSCREEN,
425     vidputs                => $tSCREEN,
426     vw_printw              => $tWINDOW,
427     vwprintw               => $tWINDOW,
428     wadd_wch               => $tWINDOW,
429     wadd_wchnstr           => $tWINDOW,
430     wadd_wchstr            => $tWINDOW,
431     waddch                 => $tWINDOW,
432     waddchnstr             => $tWINDOW,
433     waddchstr              => $tWINDOW,
434     waddnstr               => $tWINDOW,
435     waddnwstr              => $tWINDOW,
436     waddstr                => $tWINDOW,
437     waddwstr               => $tWINDOW,
438     wattr_get              => $tWINDOW,
439     wattr_off              => $tWINDOW,
440     wattr_on               => $tWINDOW,
441     wattr_set              => $tWINDOW,
442     wattroff               => $tWINDOW,
443     wattron                => $tWINDOW,
444     wattrset               => $tWINDOW,
445     wbkgd                  => $tWINDOW,
446     wbkgdset               => $tWINDOW,
447     wborder                => $tWINDOW,
448     wborder_set            => $tWINDOW,
449     wchgat                 => $tWINDOW,
450     wclear                 => $tWINDOW,
451     wclrtobot              => $tWINDOW,
452     wclrtoeol              => $tWINDOW,
453     wcolor_set             => $tWINDOW,
454     wcursyncup             => $tWINDOW,
455     wdelch                 => $tWINDOW,
456     wdeleteln              => $tWINDOW,
457     wechochar              => $tWINDOW,
458     wenclose               => $tWINDOW,
459     werase                 => $tWINDOW,
460     wget_wch               => $tWINDOW,
461     wget_wstr              => $tWINDOW,
462     wgetbkgrnd             => $tWINDOW,
463     wgetch                 => $tWINDOW,
464     wgetch_events          => $tWINDOW,
465     wgetdelay              => $tWINDOW,
466     wgetn_wstr             => $tWINDOW,
467     wgetnstr               => $tWINDOW,
468     wgetparent             => $tWINDOW,
469     wgetscrreg             => $tWINDOW,
470     wgetstr                => $tWINDOW,
471     whline                 => $tWINDOW,
472     whline_set             => $tWINDOW,
473     win_wch                => $tWINDOW,
474     win_wchnstr            => $tWINDOW,
475     win_wchstr             => $tWINDOW,
476     winch                  => $tWINDOW,
477     winchnstr              => $tWINDOW,
478     winchstr               => $tWINDOW,
479     winnstr                => $tWINDOW,
480     winnwstr               => $tWINDOW,
481     wins_nwstr             => $tWINDOW,
482     wins_wch               => $tWINDOW,
483     wins_wstr              => $tWINDOW,
484     winsch                 => $tWINDOW,
485     winsdelln              => $tWINDOW,
486     winsertln              => $tWINDOW,
487     winsnstr               => $tWINDOW,
488     winsstr                => $tWINDOW,
489     winstr                 => $tWINDOW,
490     winwstr                => $tWINDOW,
491     wmouse_trafo           => $tWINDOW,
492     wmove                  => $tWINDOW,
493     wnoutrefresh           => $tWINDOW,
494     wprintw                => $tWINDOW,
495     wredrawln              => $tWINDOW,
496     wrefresh               => $tWINDOW,
497     wresize                => $tWINDOW,
498     wscrl                  => $tWINDOW,
499     wsetscrreg             => $tWINDOW,
500     wstandend              => $tWINDOW,
501     wstandout              => $tWINDOW,
502     wsyncdown              => $tWINDOW,
503     wsyncup                => $tWINDOW,
504     wtimeout               => $tWINDOW,
505     wtouchln               => $tWINDOW,
506     wvline                 => $tWINDOW,
507 );
508
509 our $fld_nums = 0;
510 our $frm_nums = 0;
511 our $itm_nums = 0;
512 our $mnu_nums = 0;
513 our $pan_nums = 0;
514 our $scr_nums = 0;
515 our $thr_nums = 0;
516 our $trm_nums = 0;
517 our $try_nums = 0;
518 our $usr_nums = 0;
519 our $win_nums = 0;
520
521 our $curscr = "";
522 our $newscr = "";
523 our $stdscr = "";
524
525 our %fld_addr;    # FIELD*
526 our %frm_addr;    # FORM*
527 our %itm_addr;    # ITEM*
528 our %mnu_addr;    # MENU*
529 our %pan_addr;    # PANEL*
530 our %scr_addr;    # SCREEN*
531 our %thr_addr;    # thread-id
532 our %trm_addr;    # TERMINAL*
533 our %try_addr;    # tries-number
534 our %usr_addr;    # user-pointer
535 our %win_addr;    # WINDOW*
536
537 sub has_addr($) {
538     my $value  = shift;
539     my $result = 0;
540     $result = 1 if ( $value =~ /\b0x[[:xdigit:]]+\b/i );
541     return $result;
542 }
543
544 sub transaddr($) {
545     my $arg = shift;
546     my $n;
547
548     $arg =~ s/\b$curscr\b/curscr/g if ($curscr);
549     $arg =~ s/\b$newscr\b/newscr/g if ($newscr);
550     $arg =~ s/\b$stdscr\b/stdscr/g if ($stdscr);
551     if ( &has_addr($arg) ) {
552         foreach my $addr ( keys %fld_addr ) {
553             $n = $fld_addr{$addr};
554             $arg =~ s/\b$addr\b/field$n/g if ( defined $n );
555         }
556     }
557     if ( &has_addr($arg) ) {
558         foreach my $addr ( keys %frm_addr ) {
559             $n = $frm_addr{$addr};
560             $arg =~ s/\b$addr\b/form$n/g if ( defined $n );
561         }
562     }
563     if ( &has_addr($arg) ) {
564         foreach my $addr ( keys %itm_addr ) {
565             $n = $itm_addr{$addr};
566             $arg =~ s/\b$addr\b/item$n/g if ( defined $n );
567         }
568     }
569     if ( &has_addr($arg) ) {
570         foreach my $addr ( keys %mnu_addr ) {
571             $n = $mnu_addr{$addr};
572             $arg =~ s/\b$addr\b/menu$n/g if ( defined $n );
573         }
574     }
575     if ( &has_addr($arg) ) {
576         foreach my $addr ( keys %pan_addr ) {
577             $n = $pan_addr{$addr};
578             $arg =~ s/\b$addr\b/panel$n/g if ( defined $n );
579         }
580     }
581     if ( &has_addr($arg) ) {
582         foreach my $addr ( keys %scr_addr ) {
583             $n = $scr_addr{$addr};
584             $arg =~ s/\b$addr\b/screen$n/g if ( defined $n );
585         }
586     }
587     if ( &has_addr($arg) ) {
588         foreach my $addr ( keys %thr_addr ) {
589             $n = $thr_addr{$addr};
590             $arg =~ s/\b$addr\b/thread$n/g if ( defined $n );
591         }
592     }
593     if ( &has_addr($arg) ) {
594         foreach my $addr ( keys %trm_addr ) {
595             $n = $trm_addr{$addr};
596             $arg =~ s/\b$addr\b/terminal$n/g if ( defined $n );
597         }
598     }
599     if ( &has_addr($arg) ) {
600         foreach my $addr ( keys %try_addr ) {
601             $n = $try_addr{$addr};
602             $arg =~ s/\b$addr\b/tries_$n/g if ( defined $n );
603         }
604     }
605     if ( &has_addr($arg) ) {
606         foreach my $addr ( keys %usr_addr ) {
607             $n = $usr_addr{$addr};
608             $arg =~ s/\b$addr\b/user_ptr$n/g if ( defined $n );
609         }
610     }
611     if ( &has_addr($arg) ) {
612         foreach my $addr ( keys %win_addr ) {
613             $n = $win_addr{$addr};
614             $arg =~ s/\b$addr\b/window$n/g if ( defined $n );
615         }
616     }
617     if ( &has_addr($arg) ) {
618         if ( $arg =~ /add_wch\((window\d+,)?0x[[:xdigit:]]+\)/i ) {
619             $arg =~ s/(0x[[:xdigit:]]+)[)]/\&wch)/i;
620         }
621         elsif (
622             $arg =~ /color_content\((screen\d+,)?\d+(,0x[[:xdigit:]]+){3}/i )
623         {
624             $arg =~ s/(,0x[[:xdigit:]]+){3}[)]/,\&r,\&g,\&b)/i;
625         }
626         elsif ( $arg =~ /pair_content\((screen\d+,)?\d+(,0x[[:xdigit:]]+){2}/i )
627         {
628             $arg =~ s/(,0x[[:xdigit:]]+){2}[)]/,\&fg,\&bg)/i;
629         }
630     }
631     if ( &has_addr($arg) and $arg =~ /called\s+\{/ ) {
632         my $func = $arg;
633         chomp $func;
634         $func =~ s/^.*called\s+\{([[:alnum:]_]+)\(.*$/$1/;
635         if ( defined $known_p1{$func} ) {
636             my $addr = $arg;
637             my $type = $known_p1{$func};
638             chomp $addr;
639             $addr =~ s/^[^(]+\((0x[[:xdigit:]]+).*$/$1/i;
640             if ( $addr !~ /^0x[[:xdigit:]]+$/i ) {
641                 if ( $type == $tSCREEN and $addr =~ /^[^(]+\(screen\d+[,)]/ ) {
642
643                     # ignore
644                 }
645                 elsif ( $type == $tWINDOW
646                     and $addr =~
647                     /^[^(]+\((stdscr|newscr|curscr|window\d+)[,)]/ )
648                 {
649
650                     # ignore
651                 }
652                 elsif ( $type == $tTERMINAL
653                     and $addr =~ /^[^(]+\(terminal\d+[,)]/ )
654                 {
655                     # ignore
656                 }
657                 elsif ( $type == $tPANEL and $addr =~ /^[^(]+\(panel\d+[,)]/ ) {
658
659                     # ignore
660                 }
661                 elsif ( $type == $tFIELD and $addr =~ /^[^(]+\(field\d+[,)]/ ) {
662
663                     # ignore
664                 }
665                 elsif ( $type == $tMENU and $addr =~ /^[^(]+\(menu\d+[,)]/ ) {
666
667                     # ignore
668                 }
669                 elsif ( $type == $tITEM and $addr =~ /^[^(]+\(item\d+[,)]/ ) {
670
671                     # ignore
672                 }
673                 else {
674                     printf "OOPS - expected type \"%s\", skipping\n>>$addr\n",
675                       $known_p1_types{$type};
676                 }
677             }
678             elsif ( $type == $tSCREEN ) {
679                 $scr_addr{$addr} = ++$scr_nums;
680                 $arg = &transaddr($arg);
681             }
682             elsif ( $type == $tWINDOW ) {
683                 $win_addr{$addr} = ++$win_nums;
684                 $arg = &transaddr($arg);
685             }
686             elsif ( $type == $tTERMINAL ) {
687                 $trm_addr{$addr} = ++$trm_nums;
688                 $arg = &transaddr($arg);
689             }
690             elsif ( $type == $tPANEL ) {
691                 $pan_addr{$addr} = ++$pan_nums;
692                 $arg = &transaddr($arg);
693             }
694             elsif ( $type == $tFIELD ) {
695                 $fld_addr{$addr} = ++$fld_nums;
696                 $arg = &transaddr($arg);
697             }
698             elsif ( $type == $tFORM ) {
699                 $frm_addr{$addr} = ++$frm_nums;
700                 $arg = &transaddr($arg);
701             }
702             elsif ( $type == $tMENU ) {
703                 $mnu_addr{$addr} = ++$mnu_nums;
704                 $arg = &transaddr($arg);
705             }
706             elsif ( $type == $tITEM ) {
707                 $itm_addr{$addr} = ++$itm_nums;
708                 $arg = &transaddr($arg);
709             }
710         }
711     }
712
713     return $arg;
714 }
715
716 sub muncher($) {
717     my $STDIN = shift;
718
719     while (<$STDIN>) {
720         my $addr;
721         my $n;
722         my $awaiting = "";
723
724       CLASSIFY: {
725
726             next unless $_;
727
728             # just in case someone tries a file with cr/lf line-endings:
729             $_ =~ s/\r\n/\n/g;
730             $_ =~ s/\r/\n/g;
731
732             if ( $_ =~
733                 /^TRACING NCURSES version.*\(tracelevel=(0x[[:xdigit:]]+)\)/ )
734             {
735                 $tracelevel = hex $1;
736                 print;
737                 next;
738             }
739
740             my $thread = "";
741             if ( $_ =~ /^(0x[[:xdigit:]]+):/ ) {
742                 $thr_addr{$1} = ++$thr_nums unless defined $thr_addr{$1};
743                 $thread = "thread" . $thr_addr{$1} . ":";
744                 $_ =~ s/^[^:]*://;
745             }
746
747             # Transform window pointer addresses so it's easier to compare logs
748             $awaiting = "curscr" if ( $_ =~ /creating curscr/ );
749             $awaiting = "newscr" if ( $_ =~ /creating newscr/ );
750             $awaiting = "stdscr" if ( $_ =~ /creating stdscr/ );
751             $awaiting = "screen" if ( $_ =~ /^(\+ )*called \{new_prescr\(\)/ );
752             if ( $_ =~ /^create :window 0x([[:xdigit:]]+)/ ) {
753                 $addr = "0x$1";
754                 if ( $awaiting eq "curscr" ) {
755                     $curscr = $addr;
756                 }
757                 elsif ( $awaiting eq "newscr" ) {
758                     $newscr = $addr;
759                 }
760                 elsif ( $awaiting eq "stdscr" ) {
761                     $stdscr = $addr;
762                 }
763                 else {
764                     $win_addr{$addr} = $win_nums++;
765                 }
766                 $awaiting = "";
767             }
768             elsif ( $_ =~ /^create :(root|new)_panel 0x([[:xdigit:]]+)/ ) {
769                 $addr            = "0x$2";
770                 $pan_addr{$addr} = $pan_nums++;
771                 $_               = &transaddr($_);
772             }
773             elsif ( $_ =~ /^create :user_ptr 0x([[:xdigit:]]+)/ ) {
774                 $addr            = "0x$1";
775                 $usr_addr{$addr} = $usr_nums++;
776                 $_               = &transaddr($_);
777             }
778             elsif ( $_ =~ /^create :field 0x([[:xdigit:]]+)/ ) {
779                 $addr            = "0x$1";
780                 $fld_addr{$addr} = $fld_nums++;
781                 $_               = &transaddr($_);
782             }
783             elsif ( $_ =~ /^create :form 0x([[:xdigit:]]+)/ ) {
784                 $addr            = "0x$1";
785                 $frm_addr{$addr} = $frm_nums++;
786                 $_               = &transaddr($_);
787             }
788             elsif ( $_ =~ /^create :menu 0x([[:xdigit:]]+)/ ) {
789                 $addr            = "0x$1";
790                 $mnu_addr{$addr} = $mnu_nums++;
791                 $_               = &transaddr($_);
792             }
793             elsif ( $_ =~ /^create :item 0x([[:xdigit:]]+)/ ) {
794                 $addr            = "0x$1";
795                 $itm_addr{$addr} = $itm_nums++;
796                 $_               = &transaddr($_);
797             }
798             elsif ( $_ =~ /^(\+ )*called \{set_curterm\((0x[[:xdigit:]]+)\)/ ) {
799                 $trm_addr{$2} = ++$trm_nums unless defined $trm_addr{$2};
800             }
801             elsif ( $_ =~ /^(\+ )*called \{_nc_add_to_try\((0x[[:xdigit:]]+),/ )
802             {
803                 $try_addr{$2} = ++$try_nums unless defined $try_addr{$2};
804             }
805             elsif ( $_ =~ /^(\+ )*_nc_alloc_screen_sp 0x([[:xdigit:]]+)/ ) {
806                 $addr = "0x$2";
807                 $scr_addr{$addr} = ++$scr_nums unless ( $scr_addr{$addr} );
808                 $awaiting = "";
809             }
810             elsif ( $_ =~ /^(\+ )*return }0x([[:xdigit:]]+)/ ) {
811                 $addr = "0x$2";
812                 if ( $awaiting eq "screen" ) {
813                     $scr_addr{$addr} = ++$scr_nums unless ( $scr_addr{$addr} );
814                 }
815             }
816             elsif ( $_ =~ /^\.\.\.deleted win=0x([[:xdigit:]]+)/ ) {
817                 $addr = "0x$1";
818                 $_    = &transaddr($_);
819                 if ( $addr eq $curscr ) {
820                     $curscr = "";
821                 }
822                 elsif ( $addr eq $newscr ) {
823                     $newscr = "";
824                 }
825                 elsif ( $addr eq $stdscr ) {
826                     $stdscr = "";
827                 }
828                 else {
829                     undef $win_addr{$addr};
830                 }
831             }
832             elsif ( $_ =~ /^\.\.\.deleted pan=\"0x([[:xdigit:]]+)\"/ ) {
833                 $addr = "0x$1";
834                 $_    = &transaddr($_);
835                 undef $pan_addr{$addr};
836             }
837             elsif ( $_ =~ /^([+ ])*called \{free_field\(0x([[:xdigit:]]+)\)/ ) {
838                 $addr = "0x$2";
839                 $_    = &transaddr($_);
840                 undef $fld_addr{$addr};
841             }
842             elsif ( $_ =~ /^([+ ])*called \{free_form\(0x([[:xdigit:]]+)\)/ ) {
843                 $addr = "0x$2";
844                 $_    = &transaddr($_);
845                 undef $frm_addr{$addr};
846             }
847             elsif ( $_ =~ /^([+ ])*called \{free_menu\(0x([[:xdigit:]]+)\)/ ) {
848                 $addr = "0x$2";
849                 $_    = &transaddr($_);
850                 undef $mnu_addr{$addr};
851             }
852             elsif ( $_ =~ /^([+ ])*called \{free_item\(0x([[:xdigit:]]+)\)/ ) {
853                 $addr = "0x$2";
854                 $_    = &transaddr($_);
855                 undef $itm_addr{$addr};
856             }
857
858             # Compactify runs of PutAttrChar
859             if ( ( ( $tracelevel & $TR{CHARPUT} ) != 0 ) and $_ =~ /$putattr/ )
860             {
861                 my $putattr_chars = $1;
862                 my $starty        = $2;
863                 my $startx        = $3;
864                 while (<$STDIN>) {
865                     if ( $_ =~ /$putattr/ ) {
866                         $putattr_chars .= $1;
867                     }
868                     else {
869                         next if ( $_ =~ /^PUTC 0x[[:xdigit:]]+.*/ );
870                         next if ( $_ =~ /^\.\.\.skip.*/ );
871                         next if ( $_ =~ /^forced to blank.*/ );
872                         last;
873                     }
874                 }
875                 print "RUN of PutAttrChar()s:"
876                   . " \"$putattr_chars\" from ${starty}, ${startx}\n";
877                 redo CLASSIFY;
878             }
879
880             # Compactify runs of waddnstr calls
881             if ( ( ( $tracelevel & $TR{CALLS} ) != 0 ) and $_ =~ /$waddnstr/ ) {
882                 my $waddnstr_chars = $2;
883                 my $winaddr        = $1;
884                 while (<$STDIN>) {
885                     next if ( $_ =~ /^return \}0/ );
886                     if ( $_ =~ /$waddnstr/ && $1 eq $winaddr ) {
887                         $waddnstr_chars .= $2;
888                     }
889                     else {
890                         last;
891                     }
892                 }
893                 my $winaddstr = &transaddr($winaddr);
894                 print "RUN of waddnstr()s:"
895                   . " $winaddstr, \"$waddnstr_chars\"\n";
896                 redo CLASSIFY;
897             }
898
899             # More transformations can go here
900
901             # Repeated runs of anything
902             my $anyline     = &transaddr($_);
903             my $repeatcount = 1;
904             while (<$STDIN>) {
905                 if ( &transaddr($_) eq $anyline ) {
906                     $repeatcount++;
907                 }
908                 else {
909                     last;
910                 }
911             }
912             if ( $repeatcount > 1 ) {
913                 print "${repeatcount} REPEATS OF $anyline";
914             }
915             else {
916                 print $thread . $anyline;
917             }
918             redo CLASSIFY if $_;
919
920         }    # :CLASSIFY
921     }
922 }
923
924 for my $tr ( keys %TR ) {
925     $TR{$tr} = hex $TR{$tr};
926 }
927
928 if ( $#ARGV >= 0 ) {
929     while ( $#ARGV >= 0 ) {
930         my $file = shift @ARGV;
931         open my $ifh, "<", $file or die $!;
932         &muncher($ifh);
933     }
934 }
935 else {
936     &muncher( \*STDIN );
937 }
938
939 # tracemunch ends here