You can display the parts of the source code containing a given string (e.g. a given macro) using the code below.
If you are already loading the packages that you need, you can search in them. The code (between \makeatletter and \makeatother) patches the \input primitive so that each time a file is read, it is also parsed to find the given string of characters in the file. If this string is found, it will be shown on your terminal, together with a given number of lines of context. It is not at all polished code (in particular, you can only search for one string in each run).
To search in a specific file, do \FindStringInFile {1}{5}{gathered}{amsmath.sty} (will crash if the file does not exist). To search in all the files that are loaded afterwards, do \FindStringInAnyLaterFile {1}{5}{math*}. The first and second arguments are the number of lines of context to display before and after the string.
In most simple cases, the code should not break the compilation of documents, but I make no guarantee at all.
\documentclass{minimal}
\makeatletter
% Standard macros
\def\FSIF@firstoftwo#1#2{#1}
\def\FSIF@secondoftwo#1#2{#2}
\def\FSIF@ifempty@NTF #1{%
\expandafter\ifx \expandafter a\detokenize\expandafter{#1}a%
\expandafter\FSIF@firstoftwo
\else
\expandafter\FSIF@secondoftwo
\fi
}
% Declare our variables
\newread\FSIF@read
\newcount\FSIF@line@int
\newcount\FSIF@pre@context@int
\newcount\FSIF@post@context@int
\newcount\FSIF@found@int
\gdef\FSIF@context{}
\def\FSIF@lines@found{}
\def\FSIF@line@part@i{}
\def\FSIF@line@part@ii{}
\def\FSIF@message@break{}
\def\FindStringInFile#1#2#3#4{%
\FSIF@pre@context@int#1\relax
\FSIF@post@context@int#2\relax
\gdef\FSIF@context{}%
\expandafter\FSIF@aux\expandafter{\detokenize{#3}}{#4}%
\FSIF@show@context
}
\def\FSIF@show@context{%
\begingroup
\newlinechar\endlinechar
\show\FSIF@context
\endgroup
}
\def\FSIF@aux #1#2{% `#1` is now detokenized
\begingroup
% Setup for nice display
\begingroup\lccode`\*\endlinechar
\lowercase{\endgroup \def\FSIF@message@break{*--------------------%
---------- #2 ------------------------------*}}%
%
% Define a macro delimited by `#1`
\def\FSIF@line@split##1#1##2\FSIF@mark##3\FSIF@stop{%
\def\FSIF@line@part@i{##1}%
\def\FSIF@line@part@ii{##2}%
}%
%
% Prepare to read the file, line by line (detokenized)
\FSIF@line@int 0\relax
\immediate\openin\FSIF@read #2\relax
\ifeof\FSIF@read\ERROR\fi
\def\FSIF@lines@found{}%
%
% Save each line in a different control sequence, built with
% `\FSIF@fileline{<file name>}{<line number>}`.
%
% If the string was found, store the line number in
% `\FSIF@lines@found`
\loop
\unless\ifeof\FSIF@read
\readline\FSIF@read to \FSIF@line@buffer
\advance\FSIF@line@int by 1\relax
\expandafter\expandafter\expandafter\let
\FSIF@fileline{#2}{\the\FSIF@line@int}\FSIF@line@buffer
\expandafter \FSIF@line@split \FSIF@line@buffer
\FSIF@mark #1\FSIF@mark \FSIF@stop
\FSIF@ifempty@NTF \FSIF@line@part@ii {}{%
\edef\FSIF@lines@found{\FSIF@lines@found\the\FSIF@line@int,}%
}%
\repeat
%
\expandafter\edef\csname FSIF@#2@lineno\endcsname{\the\FSIF@line@int}%
%
% Then add `\FSIF@context@int` context lines around each line.
% There can be overlaps...
\edef\FSIF@lines@found{\FSIF@lines@found
\number\numexpr\the\FSIF@line@int+\the\FSIF@pre@context@int,}%
%
\FSIF@pop@lines@found
\FSIF@line@int 0\relax
\loop
\advance\FSIF@line@int by 1\relax
% If we've exhausted this found-line's context, see the next one.
\ifnum\numexpr\the\FSIF@found@int+\the\FSIF@post@context@int
<\the\FSIF@line@int\relax
\FSIF@pop@lines@found
\fi
% If we're not yet at a context, step to one.
\ifnum\numexpr\the\FSIF@found@int-\the\FSIF@pre@context@int
>\the\FSIF@line@int\relax
\FSIF@line@int\numexpr\the\FSIF@found@int-\the\FSIF@pre@context@int
\xdef\FSIF@context{\FSIF@context\FSIF@message@break}%
\fi
% Now we're in a context, so store that line.
\xdef\FSIF@context{\FSIF@context\FSIF@fileline{#2}{\the\FSIF@line@int}}%
% If we've not reached the end, we're done.
\ifnum\FSIF@line@int<\csname FSIF@#2@lineno\endcsname\relax
\repeat
\endgroup
}
\def\FSIF@fileline#1#2{\csname FSIF@#1@#2\endcsname}
\def\FSIF@pop@lines@found{%
\expandafter\FSIF@pop@lines@found@aux \FSIF@lines@found\FSIF@stop}
\def\FSIF@pop@lines@found@aux #1,#2\FSIF@stop{%
\FSIF@found@int#1\relax \def\FSIF@lines@found{#2}}
\def\FSIF@new@@@input{\expandafter\FSIF@new@@@input@aux\romannumeral-`\0}
\def\FSIF@new@@@input@aux#1 {%
\expandafter\FSIF@aux\expandafter{\FSIF@string}{#1}%
\FSIF@show@context
\FSIF@old@@@input #1 }
\def\FindStringInAnyLaterFile#1#2#3{%
\FSIF@pre@context@int#1\relax
\FSIF@post@context@int#2\relax
\edef\FSIF@string{\detokenize{#3}}%
\gdef\FSIF@context{}%
% patch `\@@input`.
\let\FSIF@old@@@input\@@input
\let\@@input\FSIF@new@@@input
}
\makeatother
%
\FindStringInFile {1}{5}{gathered}{amsmath.sty}
\FindStringInAnyLaterFile {1}{5}{math*}
\usepackage{amsmath}
\usepackage{breqn}
\begin{document}
An equation,
\begin{align*}
x^2 + y^2 &= z^2 \\
x^2 - y^2 &= t^2
\end{align*}
\end{document}