• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env perl
2# $Id: tracemunch,v 1.41 2021/09/04 10:31:03 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
37use strict;
38use warnings;
39
40$| = 1;
41
42our $putattr =
43    'PutAttrChar\(\{\{ ' . "'(.)'"
44  . ' = 0[0-7]+ \}\}\) at \(([0-9]+), ([0-9]+)\)';
45our $waddnstr =
46'^called \{waddnstr\((0x[[:xdigit:]]+|window\d+),"((\\.|[^\"]*))",[-]?[0-9]+\)';
47
48our %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
66our $tracelevel = 0;
67
68our $tSCREEN   = 1;    # SCREEN*
69our $tWINDOW   = 2;    # WINDOW*
70our $tTERMINAL = 3;    # TERMINAL*
71our $tPANEL    = 4;    # PANEL*
72our $tFIELD    = 5;    # FIELD*
73our $tFORM     = 5;    # FORM*
74our $tMENU     = 6;    # MENU*
75our $tITEM     = 7;    # ITEM*
76
77our %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:
92our %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
509our $fld_nums = 0;
510our $frm_nums = 0;
511our $itm_nums = 0;
512our $mnu_nums = 0;
513our $pan_nums = 0;
514our $scr_nums = 0;
515our $thr_nums = 0;
516our $trm_nums = 0;
517our $try_nums = 0;
518our $usr_nums = 0;
519our $win_nums = 0;
520
521our $curscr = "";
522our $newscr = "";
523our $stdscr = "";
524
525our %fld_addr;    # FIELD*
526our %frm_addr;    # FORM*
527our %itm_addr;    # ITEM*
528our %mnu_addr;    # MENU*
529our %pan_addr;    # PANEL*
530our %scr_addr;    # SCREEN*
531our %thr_addr;    # thread-id
532our %trm_addr;    # TERMINAL*
533our %try_addr;    # tries-number
534our %usr_addr;    # user-pointer
535our %win_addr;    # WINDOW*
536
537sub has_addr($) {
538    my $value  = shift;
539    my $result = 0;
540    $result = 1 if ( $value =~ /\b0x[[:xdigit:]]+\b/i );
541    return $result;
542}
543
544sub 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
716sub 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 to make it 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
924for my $tr ( keys %TR ) {
925    $TR{$tr} = hex $TR{$tr};
926}
927
928if ( $#ARGV >= 0 ) {
929    while ( $#ARGV >= 0 ) {
930        my $file = shift @ARGV;
931        open my $ifh, "<", $file or die $!;
932        &muncher($ifh);
933    }
934}
935else {
936    &muncher( \*STDIN );
937}
938
939# tracemunch ends here
940