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

조회 수: 11 (최근 30일)
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
Matthew
Matthew 2017년 12월 15일
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);

댓글을 달려면 로그인하십시오.

채택된 답변

Bradley Stiritz
Bradley Stiritz 2011년 9월 29일
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

추가 답변 (2개)

Jan
Jan 2011년 9월 25일
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
Bradley Stiritz
Bradley Stiritz 2011년 9월 26일
p.s. thank you anyway for your time & consideration. I appreciate you giving my problem some thought :)
Jan
Jan 2011년 9월 29일
@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.

댓글을 달려면 로그인하십시오.


Daniel Shub
Daniel Shub 2011년 9월 25일
I think you always want the last function on the stack:
callerFileName = stDebug(end).file;
callerLineNumber = stDebug(end).line;
  댓글 수: 2
Bradley Stiritz
Bradley Stiritz 2011년 9월 25일
Daniel,
Thanks for your response, but did you try your suggested code..? Here's what I get when I execute your modified function B():
>> B(10)
Complete text of calling code is : 'stDebug = dbstack;'
Bradley Stiritz
Bradley Stiritz 2011년 9월 25일
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)'

댓글을 달려면 로그인하십시오.

카테고리

Help CenterFile Exchange에서 Logical에 대해 자세히 알아보기

제품

Community Treasure Hunt

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

Start Hunting!

Translated by