Skip to content

Commit

Permalink
Make error output use the same stream consistently
Browse files Browse the repository at this point in the history
- Introduce a global variable GAP_ERROR_STREAM.
ErrorInner, Where, and WHERE consistently print their output to the
corresponding stream.
- Get rid of now unnecessary flush character \c in ErrorInner
- PRINT_CURRENT_STATEMENT now takes a stream as additional input.
- Adjust its tests accordingly.
  • Loading branch information
ssiccha committed Jun 12, 2018
1 parent 758a719 commit 58f12d2
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 31 deletions.
57 changes: 31 additions & 26 deletions lib/error.g
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ CallAndInstallPostRestore( function()
ASS_GVAR( "QUITTING", false );
end);

# This global variable is used by ErrorInner, Where, and WHERE to determine
# which stream they should print their output to.
# If an interactive SHELL is started by a break loop it still listens
# and prints to "*errin*" and "*errout*" respectively.
GAP_ERROR_STREAM := "*errout*";


#############################################################################
##
Expand Down Expand Up @@ -50,17 +56,17 @@ BIND_GLOBAL("WHERE", function( context, depth, outercontext)
bottom := GetBottomLVars();
lastcontext := outercontext;
while depth > 0 and context <> bottom do
PRINT_CURRENT_STATEMENT(context);
Print(" called from\n");
PRINT_CURRENT_STATEMENT(GAP_ERROR_STREAM, context);
PrintTo(GAP_ERROR_STREAM, " called from\n");
lastcontext := context;
context := ParentLVars(context);
depth := depth-1;
od;
if depth = 0 then
Print("... ");
PrintTo(GAP_ERROR_STREAM, "... ");
else
f := ContentsLVars(lastcontext).func;
Print("<function \"",NAME_FUNC(f)
PrintTo(GAP_ERROR_STREAM, "<function \"",NAME_FUNC(f)
,"\">( <arguments> )\n called from read-eval loop ");
fi;
end);
Expand All @@ -75,11 +81,11 @@ BIND_GLOBAL("Where", function(arg)
fi;

if ErrorLVars = fail or ErrorLVars = GetBottomLVars() then
Print("not in any function ");
PrintTo(GAP_ERROR_STREAM, "not in any function ");
else
WHERE(ParentLVars(ErrorLVars),depth, ErrorLVars);
fi;
Print("at ",INPUT_FILENAME(),":",INPUT_LINENUMBER(),"\n");
PrintTo(GAP_ERROR_STREAM, "at ",INPUT_FILENAME(),":",INPUT_LINENUMBER(),"\n");
end);

OnBreak := Where;
Expand Down Expand Up @@ -115,15 +121,15 @@ BIND_GLOBAL("ErrorInner",

context := arg[1].context;
if not IsLVarsBag(context) then
PrintTo("*errout*", "ErrorInner: option context must be a local variables bag\n");
PrintTo(GAP_ERROR_STREAM, "ErrorInner: option context must be a local variables bag\n");
LEAVE_ALL_NAMESPACES();
JUMP_TO_CATCH(1);
fi;

if IsBound(arg[1].justQuit) then
justQuit := arg[1].justQuit;
if not justQuit in [false, true] then
PrintTo("*errout*", "ErrorInner: option justQuit must be true or false\n");
PrintTo(GAP_ERROR_STREAM, "ErrorInner: option justQuit must be true or false\n");
LEAVE_ALL_NAMESPACES();
JUMP_TO_CATCH(1);
fi;
Expand All @@ -134,7 +140,7 @@ BIND_GLOBAL("ErrorInner",
if IsBound(arg[1].mayReturnVoid) then
mayReturnVoid := arg[1].mayReturnVoid;
if not mayReturnVoid in [false, true] then
PrintTo("*errout*", "ErrorInner: option mayReturnVoid must be true or false\n");
PrintTo(GAP_ERROR_STREAM, "ErrorInner: option mayReturnVoid must be true or false\n");
LEAVE_ALL_NAMESPACES();
JUMP_TO_CATCH(1);
fi;
Expand All @@ -145,7 +151,7 @@ BIND_GLOBAL("ErrorInner",
if IsBound(arg[1].mayReturnObj) then
mayReturnObj := arg[1].mayReturnObj;
if not mayReturnObj in [false, true] then
PrintTo("*errout*", "ErrorInner: option mayReturnObj must be true or false\n");
PrintTo(GAP_ERROR_STREAM, "ErrorInner: option mayReturnObj must be true or false\n");
LEAVE_ALL_NAMESPACES();
JUMP_TO_CATCH(1);
fi;
Expand All @@ -156,7 +162,7 @@ BIND_GLOBAL("ErrorInner",
if IsBound(arg[1].printThisStatement) then
printThisStatement := arg[1].printThisStatement;
if not printThisStatement in [false, true] then
PrintTo("*errout*", "ErrorInner: option printThisStatement must be true or false\n");
PrintTo(GAP_ERROR_STREAM, "ErrorInner: option printThisStatement must be true or false\n");
LEAVE_ALL_NAMESPACES();
JUMP_TO_CATCH(1);
fi;
Expand All @@ -167,7 +173,7 @@ BIND_GLOBAL("ErrorInner",
if IsBound(arg[1].lateMessage) then
lateMessage := arg[1].lateMessage;
if not lateMessage in [false, true] and not IsString(lateMessage) then
PrintTo("*errout*", "ErrorInner: option lateMessage must be a string or false\n");
PrintTo(GAP_ERROR_STREAM, "ErrorInner: option lateMessage must be a string or false\n");
LEAVE_ALL_NAMESPACES();
JUMP_TO_CATCH(1);
fi;
Expand All @@ -177,7 +183,7 @@ BIND_GLOBAL("ErrorInner",

earlyMessage := arg[2];
if Length(arg) <> 2 then
PrintTo("*errout*","ErrorInner: new format takes exactly two arguments\n");
PrintTo(GAP_ERROR_STREAM, "ErrorInner: new format takes exactly two arguments\n");
LEAVE_ALL_NAMESPACES();
JUMP_TO_CATCH(1);
fi;
Expand All @@ -187,34 +193,33 @@ BIND_GLOBAL("ErrorInner",
errorLVars := ErrorLVars;
ErrorLVars := context;
if QUITTING or not BreakOnError then
PrintTo("*errout*","Error, ");
PrintTo(GAP_ERROR_STREAM, "Error, ");
for x in earlyMessage do
PrintTo("*errout*",x);
PrintTo(GAP_ERROR_STREAM, x);
od;
PrintTo("*errout*","\n");
PrintTo(GAP_ERROR_STREAM, "\n");
ErrorLevel := ErrorLevel-1;
ErrorLVars := errorLVars;
if ErrorLevel = 0 then LEAVE_ALL_NAMESPACES(); fi;
JUMP_TO_CATCH(0);
fi;
PrintTo("*errout*","Error, ");
PrintTo(GAP_ERROR_STREAM, "Error, ");
for x in earlyMessage do
PrintTo("*errout*",x);
PrintTo(GAP_ERROR_STREAM, x);
od;
if printThisStatement then
if context <> GetBottomLVars() then
PrintTo("*errout*"," in\n \c");
PRINT_CURRENT_STATEMENT(context);
Print("\c");
PrintTo("*errout*"," called from \n");
PrintTo(GAP_ERROR_STREAM, " in\n ");
PRINT_CURRENT_STATEMENT(GAP_ERROR_STREAM, context);
PrintTo(GAP_ERROR_STREAM, " called from \n");
else
PrintTo("*errout*","\c\n");
PrintTo(GAP_ERROR_STREAM, "\n");
fi;
else
location := CURRENT_STATEMENT_LOCATION(context);
if location <> fail then PrintTo("*errout*", " at ", location[1], ":", location[2]);
if location <> fail then PrintTo(GAP_ERROR_STREAM, " at ", location[1], ":", location[2]);
fi;
PrintTo("*errout*"," called from\c\n");
PrintTo(GAP_ERROR_STREAM, " called from\n");
fi;

if SHOULD_QUIT_ON_BREAK() then
Expand All @@ -225,7 +230,7 @@ BIND_GLOBAL("ErrorInner",
OnBreak();
fi;
if IsString(lateMessage) then
PrintTo("*errout*",lateMessage,"\n");
PrintTo(GAP_ERROR_STREAM, lateMessage,"\n");
elif lateMessage then
if IsBound(OnBreakMessage) and IsFunction(OnBreakMessage) then
OnBreakMessage();
Expand Down
28 changes: 26 additions & 2 deletions src/error.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,22 +152,44 @@ Obj FuncCURRENT_STATEMENT_LOCATION(Obj self, Obj context)
return retlist;
}

Obj FuncPRINT_CURRENT_STATEMENT(Obj self, Obj context)

Obj FuncPRINT_CURRENT_STATEMENT(Obj self, Obj stream, Obj context)
{
if (context == STATE(BottomLVars))
return 0;

/* HACK: we want to redirect output */
/* Try to print the output to stream. Use *errout* as a fallback. */
if ((IsStringConv(stream) && !OpenOutput(CSTR_STRING(stream))) ||
(!IS_STRING(stream) && !OpenOutputStream(stream))) {
if (OpenOutput("*errout*")) {
Pr("PRINT_CURRENT_STATEMENT: can not open error stream\n", 0, 0);
}
else {
int ret = fputs("gap: panic, can not open *errout*!\n", stderr);
/* If that failed, try printing to stdout */
if (ret == EOF) {
fputs("gap: panic, can not open *errout*!\n", stdout);
}
SyExit(1);
}
}

Obj func = FUNC_LVARS(context);
GAP_ASSERT(func);
Stat call = STAT_LVARS(context);
if (IsKernelFunction(func)) {
Pr("<compiled statement> ", 0L, 0L);
/* HACK: close the output again */
CloseOutput();
return 0;
}
Obj body = BODY_FUNC(func);
if (call < OFFSET_FIRST_STAT ||
call > SIZE_BAG(body) - sizeof(StatHeader)) {
Pr("<corrupted statement> ", 0L, 0L);
/* HACK: close the output again */
CloseOutput();
return 0;
}

Expand All @@ -186,6 +208,8 @@ Obj FuncPRINT_CURRENT_STATEMENT(Obj self, Obj context)
Pr(" at %g:%d", (Int)filename, LINE_STAT(call));
}
SWITCH_TO_OLD_LVARS(currLVars);
/* HACK: close the output again */
CloseOutput();
return 0;
}

Expand Down Expand Up @@ -578,7 +602,7 @@ static StructGVarFunc GVarFuncs[] = {
GVAR_FUNC(CALL_WITH_CATCH, 2, "func, args"),
GVAR_FUNC(JUMP_TO_CATCH, 1, "payload"),

GVAR_FUNC(PRINT_CURRENT_STATEMENT, 1, "context"),
GVAR_FUNC(PRINT_CURRENT_STATEMENT, 2, "stream, context"),
GVAR_FUNC(CURRENT_STATEMENT_LOCATION, 1, "context"),

GVAR_FUNC(SetUserHasQuit, 1, "value"),
Expand Down
6 changes: 3 additions & 3 deletions tst/testinstall/kernel/gap.tst
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@ Error, usage: UpEnv( [ <depth> ] )
#
gap> CURRENT_STATEMENT_LOCATION(GetCurrentLVars());
fail
gap> PRINT_CURRENT_STATEMENT(GetCurrentLVars());
gap> f:=function() PRINT_CURRENT_STATEMENT(GetCurrentLVars()); Print("\n"); end;; f();
PRINT_CURRENT_STATEMENT( GetCurrentLVars( ) ); at stream:1
gap> PRINT_CURRENT_STATEMENT("*errout*", GetCurrentLVars());
gap> f:=function() PRINT_CURRENT_STATEMENT("*errout*", GetCurrentLVars()); Print("\n"); end;; f();
PRINT_CURRENT_STATEMENT( "*errout*", GetCurrentLVars( ) ); at stream:1
#
gap> CALL_WITH_CATCH(fail,fail);
Expand Down

0 comments on commit 58f12d2

Please sign in to comment.