Script to insert logging into every function in a project? - c++

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 call
Basically, 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.

A run-time profiler will kind of give you that information: it will tell what subroutines were called from each routine, and how many times (but not, in what sequence).

Have you considered running the code within a debugger, and simply stepping through the entire application (or otherwise setting a breakpoint on the code you're interested in and just stepping through that)? I find that to sometimes be a useful technique when faced with a large legacy code base that I didn't write.
Alternatively, if you're compiling in the VS world, consider taking a look at the /Gh and
/GH switches to cl.exe. They seem to allow you to hook function entry/exit and call some other routine. I've never used them before, but they seem to directly address your need.

Related

Binding a Lua table function to a C++ variable using LUAPlus

I want to link a Lua table function to a C++ variable using LUAPlus. So far using what information I can find on the web, I've managed to call a table function using DoString("tableName:functionName"), but I want to be able to call the function through a variable. I know its possible but I cant figure out what I'm doing wrong.
In the code I've added, pLuaState->DoString("table1:prints()") works fine and prints everything as needed.
When I try to get the function and call it using the func variable, my program crashes with
error message
Assertion failed: 0, file .../luafunciton.h, line 41
If I remove all the prints in the prints() function in Lua except "print("in prints")", everything works fine. Based on this I assume that GetByName("functionName") returns a function that doesn't contain a reference to its parent table. And this is where I get stuck.
main.cpp
pLuaState = LuaPlus::LuaState::Create(true);
pLuaState->DoFile("test.lua");
LuaObject globals = pLuaState->GetGlobals();
LuaObject metaTableObj = pLuaState->GetGlobals().Lookup("RandomMove");
if (metaTableObj.IsNil())
{
metaTableObj = pLuaState->GetGlobals().CreateTable("RandomMove");
}
metaTableObj.SetObject("__index", metaTableObj);
metaTableObj.RegisterObjectDirect("GetX", (TestLua*)0, &TestLua::GetX);
metaTableObj.RegisterObjectDirect("SetX", (TestLua*)0, &TestLua::SetX);
TestLua obj1(6);
LuaObject table1Obj = pLuaState->GetGlobals().CreateTable("table1");
table1Obj.SetLightUserData("__object", &obj1);
table1Obj.SetObject("__index", metaTableObj);
table1Obj.SetMetaTable(metaTableObj);
pLuaState->DoString("table1:prints()");
auto prints = table1Obj.GetByName("prints");
if (!prints.IsFunction())
cout << "nil function" << endl;
else
{
LuaPlus::LuaFunction<void> func(prints);
func();
}
test.lua
print("test.lua")
RandomMove =
{
_thing = 1
}
function RandomMove:SetThing()
print("I am "..tostring(self.__object))
end
function RandomMove:prints()
print("in prints")
print("__object is: " .. tostring(self.__object))
print("_thing is: ".. tostring(self._thing))
print(self:GetX())
end
Any help would be appreciated.
You are correct. Functions do not know anything about their "parents" or their "objects" or anything. That's why the : calling syntax exists. The call table1:prints() is identical to table1.prints(table1) (only lua ensures that table1 is evaluated only once.
So if you grab the function from the table/etc. directly when you call it directly you need to ensure that you pass the correct table/etc. as the first argument (before any other arguments the function expects).

search functions without some special function call in vim

I have a very large source code(>10,000lines) to change, with some function with fn_i_dont_want, I don't need to change, all other functions I must do some changes.So it's very hard to find such functions in such a large source code.
For example:
int foo_i_dont_want()
{
fn_i_dont_want()
}
int foo_i_want1()
{
fn()
fn1()
}
int foo_i_want2()
{
fn()
fn1()
....
}
I want vim to search all function I want, foo_i_want1, foo_i_want2, the condition is I don't want function with function call fn_i_dont_want.
I've tried to use vim regex like
/{\_.\{-}fn_i_dont_want\_.\{-}}
or
/{\_.*fn_i_dont_want\_.*}
But everything fails, it gets worse when there is some function like this:
int foo_i_dont_want()
{
struct bar = {0,0};
fn_i_dont_want();
}
and vim searches for everything in the pair of bracket{}.
So can somebody help me?
Parsing a complex programming language with regular expression is bound to be incomplete and problematic. Instead:
either use the refactoring capabilities of a real IDE, or
if you have to do this in Vim use :substitute with the confirm flag, and manually accept / decline each match position after inspecting it

Trash characters when using buffers in c++

I have a DLL that I need to handle in C++. I'm using WxWidgets (standard compilation, but I also tried Unicode on/off) and NetBeans. I also tried dealing with this without WxWidgets (windows.h) and had same problems.
Here is how I access the DLL functions using WxWidgets:
// -------------------- POINTERS TO FUNCTIONS
typedef bool(*TYPE_DLL_SetLicense)(char*, char*);
typedef bool(*TYPE_DLL_PingConnection)(char*);
typedef char*(*TYPE_DLL_ERR_DESCRIPTION)(void);
class DLL_Library
{
public:
// pointers to functions inside dll
TYPE_DLL_SetLicense DLL_SetLicense; //initialize - will wor fine as it returns only true/false (buffer only provide data)
TYPE_DLL_PingConnection DLL_PingConnection; //ping to serwer. Will return trahs, becouse it uses buffer to provide data ang get answear back
TYPE_DLL_ERR_DESCRIPTION DLL_ERR_DESCRIPTION; //error description. No buffer, no trouble. Returns correct string.
wxDynamicLibrary dynLib2;
int initialize(void)
{
//patch to dll
wxString path = wxStandardPaths::Get().GetExecutablePath().BeforeLast('\\') + _("\\DLL_dll\\DLLMOK.dll");
if(!wxFile::Exists(path)) return -1;
//load dll
if(!dynLib2.Load(path)) return -2;
//Assign functions in dll to variable
DLL_SetLicense=(TYPE_DLL_SetLicense) dynLib2.GetSymbol(wxT("DLL_SetLicense"));
DLL_PingConnection=(TYPE_DLL_PingConnection) dynLib2.GetSymbol(wxT("DLL_PingConnection"));
DLL_ERR_DESCRIPTION=(TYPE_DLL_ERR_DESCRIPTION) dynLib2.GetSymbol(wxT("DLL_ERROR_DESCRIPTION"));
return 0;
}
};
And here is the function I run. It should return and XML content, that I try to save to the file.
//DLL_PingConnection
//result ping to be save in file
wxFile file_ping_xml;
plik_ping_xml.Open(wxT("C:\\dll\\ping.xml"),wxFile::write);
char buffor_ping_xml[2000];
//I run the function here
bool is_ping = DLL_PingConnection(buffor_ping_xml);
if(is_ping)
{
tex_box->AppendText(wxT("DLL_PingConnection True\n"));
//we save result to file
bool is_write_ping_ok = file_ping_xml.Write(buffor_ping_xml,2000);
if (is_write_ping_ok){tex_box->AppendText(wxT("Save to file is ok ok\n"));}
else {tex_box->AppendText(wxT("Save to file failed :( \n"));}
}
else
{
tex_box->AppendText(wxT("DLL_PingConnection False\n"));
}
std::cout << "Error description: " << DLL_ERR_DESCRIPTION() << "\n"; //will work fine both in saving to file, and in streaming to screen.
The problem is that inside the file instead of good content I get rubbish like this:
NOTE that this only happens in functions that use buffers like:
char buffer[2000] //buffer will contain for example file xml
function do_sth_with_xml(buffer) //buffer containing xml will (should) be overwriten with xml results of the function - in our case DLL_PingCONNECTION should save in buffer xml with connection data
Documentation say that the DLL operates on Windows-1250. File ping.xml I have set to windows ANSI, but I don't think problem lies here.
EDIT: I have written problem without WxWidgets (I load DLL using windows.h) - same problems. Here is the code: Getting trash data in char* while using it as buffer in function . Please help :(
This
DLL_PingConnection=(TYPE_DLL_PingConnection)
shouldn't it be
DLL_PingConnection=(TYPE_DLL_PingConnection) dynLib2.GetSymbol(wxT("DLL_PingConnection"));
?
seems otherwise you will not get a valid pointer to the function in the DLL.
as a general rule you should check return values, especially from a DLL
you load dynamically since it happens that you sometimes get another version
of the DLL which may have a function with same name but other signature or
where is missing entirely.
You named a function
DLL_PingConnection=(TYPE_DLL_PingConnection) dynLib2.GetSymbol(....
and call it with
OSOZ.OSOZ_PingConnection(buffor_ping_xml);
you typedef a function
typedef bool(*TYPE_DLL_PingConnection)(char*);
you create a variable
char buffor_ping_xml[2000];
in your typedef it is char* and your buffor_ping_xml is char
how can that work ?
try
char *buffor_ping_xml = new char[2000];
/* or */
wchar_t *buffor_ping_xml = new wchar_t[2000];
/* or */
wxChar *buffor_ping_xml = new wxchar[2000];
bool is_ping = DLL_PingConnection(buffor_ping_xml);
wxString mystring = wxString::FromUTF8(buffor_ping_xml);
write mystring to file.
To Do:
look in your wxwidgets\libs folder for your libs
are there libwxmsw29ud_* with a 'u' in the name (after version number here 29)?
If not You can not use unicode
If yes next steps
for all different test char *, wchar_t *, wxChar * give the files different name.
for example file_ping_xml.Open(wxT("C:\dll\ping_w_t_FromUTF8.xml"), ...
for wchar_t * in combination with
wxString mystring = wxString::FromUTF8(buffor_ping_xml);
also in combination with
wxString mystring(buffor_ping_xml);
Then check out the look like, of the files in a browser .
To test you can go to your wxWidgets sample folder . Compile in the folder C:\wxWidgets\samples\docview\docview.cpp . Open with docview.exe a unicode file . How does it look.
Unicode download file
Unicode-related compilation settings
You should define wxUSE_UNICODE to 1 to compile your program in Unicode mode. This currently works for wxMSW, wxGTK, wxMac and wxX11. If you compile your program in ANSI mode you can still define wxUSE_WCHAR_T to get some limited support for wchar_t type.
Here is answear: Getting trash data in char* while using it as buffer in function.
Thanks everyone - expecially for patience.

How to paste xml to C++ (Tinyxml)

I'm currently working on a project in C++ where I need to read some things from a xml file, I've figured out that tinyxml seams to be the way to go, but I still don't know exactly how to do.
Also my xml file is a little tricky, because it looks a little different for every user that needs to use this.
The xml file I need to read looks like this
<?xml version="1.0" encoding="utf-8"?>
<cloud_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx xmlns:d="http://www.kuju.com/TnT/2003/Delta" d:version="1.0">
<cCareerModel d:id="154964152">
<ScenarioCareer>
<cScenarioCareer d:id="237116344">
<IsCompleted d:type="cDeltaString">CompletedSuccessfully</IsCompleted>
<BestScore d:type="sInt32">0</BestScore>
<LastScore d:type="sInt32">0</LastScore>
<ID>
<cGUID>
<UUID>
<e d:type="sUInt64">5034713268864262327</e>
<e d:type="sUInt64">2399721711294842250</e>
</UUID>
<DevString d:type="cDeltaString">0099a0b7-e50b-45de-8a85-85a12e864d21</DevString>
</cGUID>
</ID>
</cScenarioCareer>
</ScenarioCareer>
<MD5 d:type="cDeltaString"></MD5>
</cCareerModel>
</cloud_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx>
Now the goal of this program is to be able to insert some string (via. a variable) and serch for the corresponding "cScenarioCarrer d:id" and read the "IsComplete" and the "BestScore".
Those strings later need to be worked with in my program, but that I can handle.
My questions here are
A. How do I go by searching for a specific "cScenarioCareer" ID
B. How do I paste the "IsComplete" and "BestScore" into some variables in my program.
Note: The xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx string is unique for every user, so keep in mind it can be anything.
If anyone out there would like to help me, I'd be very graceful, thank you.
PS. I'd like to have some kind of understanding for what I'm doing here, all though "paste this code into your program" answers are acceptable, I think it would be much better if you can tell me how and why it works.
Since you're doing this in C++ I'll make this example using the ticpp interface to
TinyXml that available at ticpp.googlecode.com.
Assumptions:
A given xml file will contain one <cloud> tag and multiple
<cCareerModel> tags.
Each <cCareerModel> contains a single <ScenarioCareer> tag which in turn contains a single <cScenarioCareer> tag
You've parsed the xml file into a TiXmlDocument called xmlDoc
You don't need to examine the data type attributes
You don't mind using exceptions
I'll also assume that you have a context variable somewhere containing a pointer to the
<cloud> tag, like so:
ticpp::Element* cloud = xmlDoc.FirstChildElement("cloud");
Here's a function that will locate the ticpp::Element for the cScenarioCareer with
the given ID.
ticpp::Element* findScenarioCareer(const std::string& careerId)
{
try
{
// Declare an iterator to access all of the cCareerModel tags and construct an
// end iterator to terminate the loop
ticpp::Iterator<ticpp::Element> careerModel;
const ticpp::Iterator<ticpp::Element> modelEnd = careerModel.end();
// Loop over the careerModel tags
for (careerModel = cloud->FirstChildElement() ; careerModel != modelEnd ;
++careerModel)
{
// Construct loop controls to access careers
ticpp::Iterator<ticpp::Element> career;
const ticpp::Iterator<ticpp::ELement> careerEnd = career.end();
// Loop over careers
for (career = careerModel->FirstChildElement("ScenarioCareer").FirstChildElement() ;
career != careerEnd ; ++career)
{
// If the the d:id attribute value matches then we're done
if (career->GetAttributeOrDefault("d:id", "") == careerId)
return career;
}
}
}
catch (const ticpp::Exception&)
{
}
return 0;
}
Then to get at the information you want you'd do something like:
std::string careerId = "237116344";
std::string completion;
std::string score;
ticpp::Element* career = findScenarioCareer(careerId);
if (career)
{
try
{
completion = career->FirstChildElement("IsCompleted")->GetText();
score = career->FirstChildElement("BestScore")->GetText();
}
catch (const ticpp::Exception&)
{
// Handle missing element condition
}
}
else
{
// Not found
}
Naturally I haven't compiled or tested any of this, but it should give you the idea.

What is the easiest way to expose M-file subfunctions for unit testing?

I have been tinkering lately with fully integrating continuous testing into my Matlab development cycle and have run across a problem I don't know how to get around. As almost all users know, Matlab kindly hides sub-functions within an M-file from the view of any functions outside that M-file. A toy example can be seen below:
function [things] = myfunc(data)
[stuff] = mysubfunc(data)
things = mean(stuff);
end
I want to perform unit testing on subfunc itself. This is, AFAIK, impossible because I cannot call it from any external function.
I'm currently using Matlab xUnit by Steve Eddins and cannot get around this issue. The easy solution -- splitting subfunc out to its own M-file -- is not acceptable in practice because I will have numerous small functions I want to test and don't want to pollute my filesystem with a separate M-file for each one. What can I do to write and perform easy unit tests without making new files for each function I want to test?
What you need to do in general is get function handles to your subfunctions from within the primary function and pass them outside the function where you can unit test them. One way to do this is to modify your primary function such that, given a particular set of input arguments (i.e. no inputs, some flag value for an argument, etc.), it will return the function handles you need.
For example, you can add a few lines of code to the beginning of your function so that it returns all of the subfunction handles when no input is specified:
function things = myfunc(data)
if nargin == 0 % If data is not specified...
things = {#mysubfunc #myothersubfunc}; % Return a cell array of
% function handles
return % Return from the function
end
% The normal processing for myfunc...
stuff = mysubfunc(data);
things = mean(stuff);
end
function mysubfunc
% One subfunction
end
function myothersubfunc
% Another subfunction
end
Or, if you prefer specifying an input flag (to avoid any confusion associated with accidentally calling the function with no inputs as Jonas mentions in his comment), you could return the subfunction handles when the input argument data is a particular character string. For example, you could change the input checking logic in the above code to this:
if ischar(data) && strcmp(data, '-getSubHandles')
I have a pretty hacky way to do this. Not perfect but at least it's possible.
function [things] = myfunc(data)
global TESTING
if TESTING == 1
unittests()
else
[stuff] = mysubfunc(data);
things = mean(stuff);
end
end
function unittests()
%%Test one
tdata = 1;
assert(mysubfunc(tdata) == 3)
end
function [stuff] = mysubfunc(data)
stuff = data + 1;
end
Then at the prompt this will do the trick:
>> global TESTING; TESTING = 1; myfunc(1)
??? Error using ==> myfunc>unittests at 19
Assertion failed.
Error in ==> myfunc at 6
unittests()
>> TESTING = 0; myfunc(1)
ans =
2
>>
Have you used the new-style classes? You could turn that function in to a static method on a utility class. Then you could either turn the subfunctions in to other static methods, or turn the subfunctions in to local functions to the class, and give the class a static method that returns the handles to them.
classdef fooUtil
methods (Static)
function [things] = myfunc(data)
[stuff] = mysubfunc(data);
things = mean(stuff);
end
function out = getLocalFunctionHandlesForTesting()
onlyAllowThisInsideUnitTest();
out.mysubfunc = #mysubfunc;
out.sub2 = #sub2;
end
end
end
% Functions local to the class
function out = mysubfunc(x)
out = x .* 2; % example dummy logic
end
function sub2()
% ...
end
function onlyAllowThisInsideUnitTest()
%ONLYALLOWTHISINSIDEUNITTEST Make sure prod code does not depend on this encapsulation-breaking feature
isUnitTestRunning = true; % This should actually be some call to xUnit to find out if a test is active
assert(isUnitTestRunning, 'private function handles can only be grabbed for unit testing');
end
If you use the classdef style syntax, all these functions, and any other methods, can all go in a single fooUtil.m file; no filesystem clutter. Or, instead of exposing the private stuff, you could write the test code inside the class.
I think the unit testing purists will say you shouldn't be doing this at all, because you should be testing against the public interface of an object, and if you need to test the subparts they should be factored out to something else that presents them in its public interface. This argues in favor of making them all public static methods and testing directly against them, forgetting about exposing private functions with function handles.
classdef fooUtil
methods (Static)
function [things] = myfunc(data)
[stuff] = fooUtil.mysubfunc(data);
things = mean(stuff);
end
function out = mysubfunc(x)
out = x .* 2; % example dummy logic
end
function sub2()
% ...
end
end
end
I use a method that mirrors the way GUIDE use to generate its entry methods. Granted it's biased towards GUIs...
Foo.m
function varargout=foo(varargin)
if nargin > 1 && ischar(varargin{1}) && ~strncmp( varargin{1},'--',2)
if nargout > 0
varargout = feval( varargin{:} );
else
feval = ( varargout{:} );
else
init();
end
This allows you to do the following
% Calls bar in foo passing 10 and 1
foo('bar', 10, 1)