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

11 visualizaciones (últimos 30 días)
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 comentario
Matthew
Matthew el 15 de Dic. de 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);

Iniciar sesión para comentar.

Respuesta aceptada

Bradley Stiritz
Bradley Stiritz el 29 de Sept. de 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

Más respuestas (2)

Jan
Jan el 25 de Sept. de 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 comentarios
Bradley Stiritz
Bradley Stiritz el 26 de Sept. de 2011
p.s. thank you anyway for your time & consideration. I appreciate you giving my problem some thought :)
Jan
Jan el 29 de Sept. de 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.

Iniciar sesión para comentar.


Daniel Shub
Daniel Shub el 25 de Sept. de 2011
I think you always want the last function on the stack:
callerFileName = stDebug(end).file;
callerLineNumber = stDebug(end).line;
  2 comentarios
Bradley Stiritz
Bradley Stiritz el 25 de Sept. de 2011
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 el 25 de Sept. de 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)'

Iniciar sesión para comentar.

Categorías

Más información sobre Logical en Help Center y File Exchange.

Productos

Community Treasure Hunt

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

Start Hunting!

Translated by