Skip to content

Commit 7027162

Browse files
committed
[[ Log ]] Implement log command
1 parent 93f302e commit 7027162

File tree

7 files changed

+174
-2
lines changed

7 files changed

+174
-2
lines changed

docs/dictionary/command/log.lcdoc

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
Name: log
2+
3+
Type: command
4+
5+
Syntax: log [ <argumentList> ]
6+
7+
Summary:
8+
Invokes the <logMessage> if it is not empty.
9+
10+
Introduced: 9.5
11+
12+
OS: mac, windows, linux, ios, android, html5
13+
14+
Platforms: desktop, server, mobile
15+
16+
Example:
17+
on preOpenStack
18+
-- uBuildMode property set before building standalone
19+
if the uBuildMode of this stack is "release" then
20+
set the logMessage to empty
21+
end if
22+
23+
loadResources
24+
end preOpenStack
25+
26+
command loadResources
27+
log "loading resources"
28+
end loadResources
29+
30+
on log pInfo
31+
-- unhandled put will go to system logs
32+
put pInfo
33+
end log
34+
35+
Parameters:
36+
argumentList:
37+
A comma separated list of expressions containing the arguments to send.
38+
Arrays are expressions and are valid to send as arguments.
39+
40+
Description:
41+
The <log> command invokes the <logMessage> handler. When the <logMessage> is the
42+
default value of `log` then the <log> command behaves in the same way as any
43+
other scripted handler. If the <logMessage> is set to empty then the <log>
44+
command does not invoke any handler or evaluate parameters, therefore, allowing
45+
for many logs to be added to scripts for development and an easy low-cost method
46+
to turn the logging off for a release build. The <logMessage> may be set to any
47+
handler name, however, if the handler is not in the message path then use of the
48+
<log> command will throw a `can't find handler` error.
49+
50+
References: log (command), put (command), msgChanged (message)
51+
52+
Tags: debugging

engine/src/cmds.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1020,6 +1020,26 @@ class MCDispatchCmd: public MCStatement
10201020
virtual void exec_ctxt(MCExecContext &ctxt);
10211021
};
10221022

1023+
class MCLogCmd: public MCStatement
1024+
{
1025+
MCParameter *params;
1026+
struct
1027+
{
1028+
unsigned container_count : 16;
1029+
};
1030+
1031+
public:
1032+
MCLogCmd(void)
1033+
{
1034+
params = nullptr;
1035+
container_count = 0;
1036+
}
1037+
~MCLogCmd(void);
1038+
1039+
virtual Parse_stat parse(MCScriptPoint& sp);
1040+
virtual void exec_ctxt(MCExecContext &ctxt);
1041+
};
1042+
10231043
class MCFocus : public MCStatement
10241044
{
10251045
MCChunk *object;

engine/src/cmdse.cpp

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,101 @@ void MCDispatchCmd::exec_ctxt(MCExecContext &ctxt)
527527
MCKeywordsExecTeardownCommandOrFunction(params);
528528
}
529529

530+
MCLogCmd::~MCLogCmd(void)
531+
{
532+
while(params != NULL)
533+
{
534+
MCParameter *t_param;
535+
t_param = params;
536+
params = params -> getnext();
537+
delete t_param;
538+
}
539+
}
540+
541+
Parse_stat MCLogCmd::parse(MCScriptPoint& sp)
542+
{
543+
initpoint(sp);
544+
545+
if (getparams(sp, &params) != PS_NORMAL)
546+
{
547+
MCperror -> add(PE_STATEMENT_BADPARAMS, sp);
548+
return PS_ERROR;
549+
}
550+
551+
/* If there are any parameters then compute the number of containers needed
552+
* to execute the command. */
553+
if (params != nullptr)
554+
{
555+
container_count = params->count_containers();
556+
}
557+
558+
return PS_NORMAL;
559+
}
560+
561+
// This method follows along the same lines as MCComref::exec
562+
void MCLogCmd::exec_ctxt(MCExecContext &ctxt)
563+
{
564+
// no-op if logMessage is empty
565+
if (MCNameIsEmpty(MClogmessage))
566+
{
567+
return;
568+
}
569+
570+
/* Attempt to allocate the number of containers needed for the call. */
571+
MCAutoPointer<MCContainer[]> t_containers = new MCContainer[container_count];
572+
if (!t_containers)
573+
{
574+
ctxt.LegacyThrow(EE_NO_MEMORY);
575+
return;
576+
}
577+
578+
/* If the argument list is successfully evaluated, then do the dispatch. */
579+
if (MCKeywordsExecSetupCommandOrFunction(ctxt,
580+
params,
581+
*t_containers,
582+
line,
583+
pos,
584+
false))
585+
{
586+
if (!ctxt.HasError())
587+
{
588+
ctxt.SetLineAndPos(line, pos);
589+
MCHandler * t_handler = nullptr;
590+
MCKeywordsExecResolveCommandOrFunction(ctxt, MClogmessage, false, t_handler);
591+
MCKeywordsExecCommandOrFunction(ctxt, t_handler, params, MClogmessage, line, pos, false, false);
592+
}
593+
}
594+
595+
/* Clean up the evaluated argument list */
596+
MCKeywordsExecTeardownCommandOrFunction(params);
597+
598+
if (MCresultmode == kMCExecResultModeReturn)
599+
{
600+
// Do nothing!
601+
}
602+
else if (MCresultmode == kMCExecResultModeReturnValue)
603+
{
604+
// Set 'it' to the result and clear the result
605+
MCAutoValueRef t_value;
606+
if (!MCresult->eval(ctxt, &t_value))
607+
{
608+
ctxt.Throw();
609+
return;
610+
}
611+
612+
ctxt.SetItToValue(*t_value);
613+
ctxt.SetTheResultToEmpty();
614+
}
615+
else if (MCresultmode == kMCExecResultModeReturnError)
616+
{
617+
// Set 'it' to empty
618+
ctxt.SetItToEmpty();
619+
// Leave the result as is but make sure we reset the 'return mode' to default.
620+
MCresultmode = kMCExecResultModeReturn;
621+
}
622+
}
623+
624+
530625
Parse_stat MCMessage::parse(MCScriptPoint &sp)
531626
{
532627
initpoint(sp);

engine/src/handler.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,9 @@ Parse_stat MCHandler::parse(MCScriptPoint &sp, Boolean isprop)
169169

170170
const LT *te;
171171
// MW-2010-01-08: [[Bug 7792]] Check whether the handler name is a reserved function identifier
172+
// special case log command is a permitted handler name
172173
if (t_type != ST_ID ||
173-
sp.lookup(SP_COMMAND, te) != PS_NO_MATCH ||
174+
(sp.lookup(SP_COMMAND, te) != PS_NO_MATCH && te -> which != S_LOG) ||
174175
(sp.lookup(SP_FACTOR, te) != PS_NO_MATCH &&
175176
te -> type == TT_FUNCTION))
176177
{

engine/src/lextable.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,7 @@ const LT command_table[] =
363363
{"load", TT_STATEMENT, S_LOAD},
364364
{"local", TT_STATEMENT, S_LOCAL},
365365
{"lock", TT_STATEMENT, S_LOCK},
366+
{"log", TT_STATEMENT, S_LOG},
366367
{"mark", TT_STATEMENT, S_MARK},
367368
{"modal", TT_STATEMENT, S_MODAL},
368369
{"modeless", TT_STATEMENT, S_MODELESS},

engine/src/newobj.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,9 @@ MCStatement *MCN_new_statement(int2 which)
164164
return new MCLocalVariable;
165165
case S_LOCK:
166166
return new MCLock;
167-
case S_MARK:
167+
case S_LOG:
168+
return new MCLogCmd;
169+
case S_MARK:
168170
return new MCMarkCommand;
169171
case S_MODAL:
170172
return new MCModal;

engine/src/parsedef.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2062,6 +2062,7 @@ enum Statements {
20622062
S_LOCAL,
20632063
S_LOAD,
20642064
S_LOCK,
2065+
S_LOG,
20652066
S_MARK,
20662067
S_MODAL,
20672068
S_MODELESS,

0 commit comments

Comments
 (0)