MATLAB Answers

Within a function : get complete command-line calling text, a la dbstack()..?

24 views (last 30 days)
Brad Stiritz
Brad Stiritz on 25 Sep 2011
Commented: Matthew on 15 Dec 2017
Hi everyone,
I understand how to use dbstack(), within a saved M-function, to get the complete text of the command which called the current function. For example, if we have two M-files, A.m & B.m, where A() calls (B):
FILE 'A.m'
function output = A(input)
output = B(input);
FILE 'B.m'
function output = B(input)
% ---------------------------------------------------------------------
% What line of text called this function..?
% ---------------------------------------------------------------------
% Get call-stack info:
stDebug = dbstack;
% We know a-priori that this function's caller info is in (stDebug)(2)
% Get caller file name & line number of code which called this function:
callerFileName = stDebug(2).file;
callerLineNumber = stDebug(2).line;
% Open caller file:
fCaller = fopen(callerFileName);
% Iterate through lines to get to desired line number:
for iLine = 1 : callerLineNumber
% Read current line of text:
currLine = fgetl(fCaller);
end
% (currLine) now reflects calling desired code: display this code:
fprintf('Complete text of calling code is : ''%s''\n',currLine);
% Close caller file:
fclose(fCaller);
% ---------------------------------------------------------------------
% Determine function output
% ---------------------------------------------------------------------
% Arbitrary operation just for demonstration:
output = input + 5;
If we call A() from the command-line, we get:
>> A(10)
Complete text of calling code is : 'output = B(input);'
ans = 15
However, if we call B() directly from the command-line, we get an error, b/c there is no 2nd element in the dbstack() output. In other words, for this case dbstack() output is a single-element structure containing info for the local function B() context only:
>> B(10)
Index exceeds matrix dimensions.
Error in B (line 12)
callerFileName = stDebug(2).file;
My problem : I need a way to programmatically get the complete literal calling text, within function B(), no matter whether the caller is another M-file or the command-line.
I thought of looking in the MATLAB diary file, but apparently it's not guaranteed the last line of the diary text file will reflect the currently-executing command-line command at any given point in the executing call stack..
Any suggestions greatly appreciated!
Thanks, Brad
  1 Comment
Matthew
Matthew on 15 Dec 2017
This isn't an answer to the question as it won't work for command line calls, but its worth noting that there are ways to get a calling line without scanning the file the calling line is in.
A pretty simple way is to create an error, and then use the getReport function on the MatlabException object.
try
error('DummyError');
catch ME
callStackDetails = getReport(ME);
end
callLine = regexp(callStackDetails,'(?<=Error in [^\n]*\n)[^\n]*','match','once');
callLine = strtrim(callLine);

Sign in to comment.

Accepted Answer

Brad Stiritz
Brad Stiritz on 29 Sep 2011
I was able to find a solution, with help from Google, by searching for : matlab "command history". After all that tedious debate above, it's nice to see a four-line solution, which I've verified with limited testing. Note that it relies completely on undocumented MATLAB functionality.
Sincere thanks to StackOverflow.com for this solution. Hope it can help s/o else as well..
function str = getLastMATLABcommandLineStr()
% Function returns a string containing the last command entered in the Matlab Command Window..
% Code via : http://stackoverflow.com/questions/5053692/how-do-i-search-through-matlab-command-history
% Get session history from Java object:
history = ...
com.mathworks.mlservices.MLCommandHistoryServices.getSessionHistory;
% Convert to a vector of char strings:
historyText = char(history);
% Convert to a cell vector of strings:
cvHistory = cellstr(historyText);
% Extract last string:
str = cvHistory{end};
end

More Answers (2)

Jan
Jan on 25 Sep 2011
Sorry for this not being an direct answer:
There are very likely cleaner methods than parsing the contents of the calling line. The input can be a function, which has side-effects such that a textual pasing will not be successful. This method will fail if called from a Mex function or a P-coded fail also.
Reading the program text of the caller is another variant of the old EVAL problems. Therefore I strongly recommend to find a more direct solution, which si safer, cleaner and is less prone to errors.
  7 Comments
Jan
Jan on 29 Sep 2011
@Brad: "Can you think of any software which asks the user to enter the same information twice, but does not validate the entries against each other?" Yes, Windows UAC. And I agree that it is a good idea not to compete with it.
And I agree, that my answer does *not* solve your problem.

Sign in to comment.


Daniel Shub
Daniel Shub on 25 Sep 2011
I think you always want the last function on the stack:
callerFileName = stDebug(end).file;
callerLineNumber = stDebug(end).line;
  2 Comments
Brad Stiritz
Brad Stiritz on 25 Sep 2011
Just to clarify, here's the call-stack output we wish to generate when B() is called from the command-line:
>>B(10)
Complete text of calling code is : 'B(10)'

Sign in to comment.

Categories

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!