I have inherited a fairly large codebase, 90% C++, and I need to get up to speed on it quickly. There are hundreds of .cc files in a wide directory tree structure.
It's fairly complex, and has no logging. In order to figure out how some major subsystems work, I want to insert a function call into every function.
E.g., given a .cc file full of stuff like this:
void A::foo(int a, int b) {
// ...
}
void A::bar() {
// ...
}
void B::bleh(const string& in) {
// ...
}
I'd like to get this:
void A::foo(int a, int b) {
LOG(debug) << "A::foo() called.";
// ...
}
void A::bar() {
LOG(debug) << "A::bar() called.";
// ...
}
void B::bleh(const string& in) {
LOG(debug) << "B::bleh() called.";
// ...
}
This can be done via python script, CMD script, power shell script, etc. If there is a way to make VS do it, great. Whatever works. Doesn't have to be pretty, I'm not checking any of this in.
Also, it doesn't necessarily need to get everything. E.g. nested classes, implementations in header files, etc.
Had something similar for adding profiling code using Macros in VS, here's the code (this also groups everything under a single "undo" command and lists all of the changes in its own output window)
Imports System
Imports EnvDTE
Imports EnvDTE80
Imports System.Diagnostics
Public Module Module1
Function GetOutputWindowPane(ByVal Name As String, Optional ByVal show As Boolean = True) As OutputWindowPane
Dim window As Window
Dim outputWindow As OutputWindow
Dim outputWindowPane As OutputWindowPane
window = DTE.Windows.Item(EnvDTE.Constants.vsWindowKindOutput)
If show Then window.Visible = True
outputWindow = window.Object
Try
outputWindowPane = outputWindow.OutputWindowPanes.Item(Name)
Catch e As System.Exception
outputWindowPane = outputWindow.OutputWindowPanes.Add(Name)
End Try
outputWindowPane.Activate()
Return outputWindowPane
End Function
Const ToInsert As String = "/* Inserted text :D */"
Sub AddProfilingToFunction(ByVal func As CodeFunction2)
Dim editPoint As EditPoint2 = func.StartPoint.CreateEditPoint()
While editPoint.GetText(1) <> "{"
editPoint.CharRight()
End While
editPoint.CharRight()
editPoint.InsertNewLine(1)
Dim insertStartLine As Integer = editPoint.Line
Dim insertStartChar As Integer = editPoint.LineCharOffset
editPoint.Insert(ToInsert)
GetOutputWindowPane("Macro Inserted Code").OutputString( _
editPoint.Parent.Parent.FullName & _
"(" & insertStartLine & "," & insertStartChar & _
") : Inserted Code """ & ToInsert & """" & vbCrLf)
End Sub
Sub AddProfilingToProject(ByVal proj As Project)
If Not proj.CodeModel() Is Nothing Then
Dim EventTitle As String = "Add Profiling to project '" & proj.Name & "'"
GetOutputWindowPane("Macro Inserted Code").OutputString("Add Profiling to project '" & proj.Name & "'" & vbCrLf)
DTE.UndoContext.Open(EventTitle)
Try
Dim allNames As String = ""
For i As Integer = 1 To proj.CodeModel().CodeElements.Count()
If proj.CodeModel().CodeElements.Item(i).Kind = vsCMElement.vsCMElementFunction Then
AddProfilingToFunction(proj.CodeModel().CodeElements.Item(i))
End If
Next
Finally
DTE.UndoContext.Close()
End Try
GetOutputWindowPane("Macro Inserted Code").OutputString(vbCrLf)
End If
End Sub
Sub AddProfilingToSolution()
GetOutputWindowPane("Macro Inserted Code").Clear()
If Not DTE.Solution Is Nothing And DTE.Solution.IsOpen() Then
For i As Integer = 1 To DTE.Solution.Projects.Count()
AddProfilingToProject(DTE.Solution.Projects.Item(i))
Next
End If
End Sub
End Module
P.S Remember to change the "Const ToInsert As String = ..." to the code you actually want to be inserted
Since you're using Visual C++, and it seems you only need the name of the function called, it might be possible to automate this further using the following command-line switches to cl.exe
:
/Gh
: Enable _penter
function call/GH
: Enable _pexit
function callBasically, providing these switches means that the compiler will automatically inject calls to functions named _penter()
and _pexit()
whenever any function begins or ends. You can then provide a separately-compiled module that implements these two functions, which either (a) calls some helper library such as DbgHelp to determine the name of the called function, or (b) just grabs the return address from the stack and prints it verbatim -- afterwards, write a script to transform these addresses into function names by looking at e.g. the linker map file produced if you pass /link /MAP:mymapfile.txt
to cl.exe
.
Of course, you'll need to put your _penter()
and _pexit()
in a separate module with /Gh
and /GH
turned off to avoid infinite recursion! :)
I did it some years ago in VS.
Regex will help you.
BTW, it not nesasary to insert different string. You can add the same string like:
LOG(debug) << __FUNCTION__ << " called.";
EDIT
something like this regexp (valid for VS only):
(void|char|int):b+:i\:\::i\([^(]*\):b*\{
You should extend the regexp depending of your needs.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With