.\" trace.tmac .\" .\" Load this before a macro package that you want to trace. .\" .\" .\" Copyright (C) 1989-2020 Free Software Foundation, Inc. .\" Written by James Clark (jjc@jclark.com) .\" .\" This file is part of groff. .\" .\" groff is free software; you can redistribute it and/or modify it .\" under the terms of the GNU General Public License as published by .\" the Free Software Foundation, either version 3 of the License, or .\" (at your option) any later version. .\" .\" groff is distributed in the hope that it will be useful, but WITHOUT .\" ANY WARRANTY; without even the implied warranty of MERCHANTABILITY .\" or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public .\" License for more details. .\" .\" You should have received a copy of the GNU General Public License .\" along with this program. If not, see .\" . .\" . . .\" Tracing within groff means replacing the original macros or requests .\" with special versions which act as wrappers to emit tracing .\" information. A natural consequence of creating such wrappers is .\" that arguments must be expanded once more. In most cases it doesn't .\" matter, however, sometimes it makes a difference. .\" .\" To limit side effects, only macros are traced by default, together .\" with some requests like '.return' which don't take (user) arguments. .\" If you want more tracing, especially of number and string register .\" assignments, add the '-r trace-full=1' command-line option. . . .\" Regarding the usage of '.do': All lines of macros which should work .\" in compatibility mode must be protected if they contain GNU troff .\" extensions and are defined with '.de'. Example: '.ds', but not .\" '.ds1', since the latter can't be called in compatibility mode. . . .do if d !!!sp \ . nx . .do nr *groff_trace_tmac_C \n[.cp] .cp 0 . .ds !!!sp " \" . .de !!c .. . . .eo . .rn return !!return . .de1 return . tm1 "\*[!!!sp]*** return . !!return twice .. . .ec . .ie r trace-full \{\ . eo . . rn nr !!nr . . de nr . do ecs . ec . do !!nr \$* . do tm1 "\*[!!!sp]*** .nr \$* (-> \n[\$1]) . do ecr . . . . rn ds !!ds . rn ds1 !!ds1 . rn as !!as . rn as1 !!as1 . . de ds . do ecs . ec . do tm1 "\*[!!!sp]*** .ds \$^ . do !!ds \$^\" . do ecr . . . . de1 ds1 . ecs . ec . tm1 "\*[!!!sp]*** .ds1 \$^ . !!ds1 \$^\" . ecr . . . . de as . do ecs . ec . do tm1 "\*[!!!sp]*** .as \$^ . do !!as \$^\" . do ecr . . . . de1 as1 . ecs . ec . tm1 "\*[!!!sp]*** .as1 \$^ . !!as1 \$^\" . ecr . . . . rn substring !!substring . . de1 substring . ecs . ec . !!substring \$* . tm1 "\*[!!!sp]*** .substring \$* (-> '\*[\$1]') . ecr . . . . rn so !!so . . de so . do ecs . ec . do tm1 "\*[!!!sp]*** .so \$* { . do !!as !!!sp " \" . do ecr . do !!so \$* . do ecs . ec . do !!substring !!!sp 1 . do tm1 "\*[!!!sp]*** } . do ecr . . . . !!c We must use '.de' for the redefinition of .mso to avoid . !!c side effects; for example, it might be called with . !!c '.do mso ...'. . . rn mso !!mso . . de mso . do ecs . ec . do tm1 "\*[!!!sp]*** .mso \$* { . do !!as !!!sp " \" . do ecr . do !!mso \$* . do ecs . ec . do !!substring !!!sp 1 . do tm1 "\*[!!!sp]*** } . do ecr . . . . ec .\} .el \{\ . als !!ds ds . als !!as as . als !!substring substring .\} . . .eo . .rn als !!als . .de1 als . ecs . ec . !!als \$* . if d !!\$2 \ . !!als !!\$1 !!\$2 . tm1 "\*[!!!sp]*** .als \$* . ecr .. . .rn rm !!rm . .de1 rm . ecs . ec . !!rm \$* . if d !!\$1 \ . !!rm !!\$1 . tm1 "\*[!!!sp]*** .rm \$* . ecr .. . .rn rn !!rn . .de rn . do ecs . ec . do !!rn \$* . do if d !!\$1 \ . !!rn !!\$1 !!\$2 . do tm1 "\*[!!!sp]*** .rn \$* . do ecr .. . .!!c Now the central tracing macros. The redefined 'de' macros .!!c create wrapper macros 'foo' which emit tracing messages .!!c before and after the call to the traced macro '!!foo'. .!!c .!!c Note that we define '!!foo' in advance so that an alias to .!!c '!!!!foo' is possible. The latter occurs if 'foo' is .!!c called as \\[foo]. .!!c .!!c The call to 'dei' must be the last instruction in the macro .!!c (since it continues the definition of the macro to trace). . .!!rn de !!de .!!rn de1 !!de1 . .!!de de . do ecs . ec . do !!de \$1 . do ie \\n[.br] .do !!ds !!!br .\" . el .do !!ds !!!br '\" . ie "\$1"\\$0" .do tm1 "\\*[!!!sp]*** de trace enter: \\*[!!!br]\\$0 \\$@ . el .do tm1 "\\*[!!!sp]*** de trace enter \$1: \\*[!!!br]\\$0 \\$@ . do !!as !!!sp " \" . . do nop \\*[!!\\$0]\\ . . do !!substring !!!sp 1 . do ie \\n[.br] .do !!ds !!!br .\" . el .do !!ds !!!br '\" . ie "\$1"\\$0" .do tm1 "\\*[!!!sp]*** trace exit: \\*[!!!br]\\$0 \\$@ . el .do tm1 "\\*[!!!sp]*** trace exit \$1: \\*[!!!br]\\$0 \\$@ \.. . . do tm1 "\*[!!!sp]*** .de \$* . . do !!ds !!d1 !!\$1\" . do !!ds !!d2 \$2\" . do ecr . do dei !!d1 !!d2 .. . .!!de1 de1 . ecs . ec . !!de1 \$1 . ie \\n[.br] .!!ds !!!br .\" . el .!!ds !!!br '\" . ie "\$1"\\$0" .tm1 "\\*[!!!sp]*** de1 trace enter: \\*[!!!br]\\$0 \\$@ . el .tm1 "\\*[!!!sp]*** de1 trace enter \$1: \\*[!!!br]\\$0 \\$@ . !!as !!!sp " \" . . nop \\*[!!\\$0]\\ . . !!substring !!!sp 1 . ie \\n[.br] .!!ds !!!br .\" . el .!!ds !!!br '\" . ie "\$1"\\$0" .tm1 "\\*[!!!sp]*** trace exit: \\*[!!!br]\\$0 \\$@ . el .tm1 "\\*[!!!sp]*** trace exit \$1: \\*[!!!br]\\$0 \\$@ \.. . . tm1 "\*[!!!sp]*** .de1 \$* . . !!ds !!d1 !!\$1\" . !!ds !!d2 \$2\" . ecr . dei1 !!d1 !!d2 .. . .!!rn am !!am .!!rn am1 !!am1 . .!!de am . do ecs . ec . do !!de \$1 . do ie \\n[.br] .do !!ds !!!br .\" . el .do !!ds !!!br '\" . ie "\$1"\\$0" .do tm1 "\\*[!!!sp]*** am trace enter: \\*[!!!br]\\$0 \\$@ . el .do tm1 "\\*[!!!sp]*** am trace enter \$1: \\*[!!!br]\\$0 \\$@ . do !!as !!!sp " \" . . do nop \\*[!!\\$0]\\ . . do !!substring !!!sp 1 . do ie \\n[.br] .do !!ds !!!br .\" . el .do !!ds !!!br '\" . ie "\$1"\\$0" .do tm1 "\\*[!!!sp]*** trace exit: \\*[!!!br]\\$0 \\$@ . el .do tm1 "\\*[!!!sp]*** trace exit \$1: \\*[!!!br]\\$0 \\$@ \.. . . do tm1 "\*[!!!sp]*** .am \$* . . do !!ds !!a1 !!\$1\" . do !!ds !!a2 \$2\" . do ecr . do ami !!a1 !!a2 .. . .!!de1 am1 . ecs . ec . !!de1 \$1 . ie \\n[.br] .!!ds !!!br .\" . el .!!ds !!!br '\" . ie "\$1"\\$0" .tm1 "\\*[!!!sp]*** am1 trace enter: \\*[!!!br]\\$0 \\$@ . el .tm1 "\\*[!!!sp]*** am1 trace enter \$1: \\*[!!!br]\\$0 \\$@ . !!as !!!sp " \" . . nop \\*[!!\\$0]\\ . . !!substring !!!sp 1 . ie \\n[.br] .!!ds !!!br .\" . el .!!ds !!!br '\" . ie "\$1"\\$0" .tm1 "\\*[!!!sp]*** trace exit: \\*[!!!br]\\$0 \\$@ . el .tm1 "\\*[!!!sp]*** trace exit \$1: \\*[!!!br]\\$0 \\$@ \.. . . tm1 "\*[!!!sp]*** .am1 \$* . . !!ds !!a1 !!\$1\" . !!ds !!a2 \$2\" . ecr . ami1 !!a1 !!a2 .. . . .ec . .cp \n[*groff_trace_tmac_C] .do rr *groff_trace_tmac_C . .\" Local Variables: .\" mode: nroff .\" fill-column: 72 .\" End: .\" vim: set filetype=groff textwidth=72: