diff --git a/apps/apps_container.cpp b/apps/apps_container.cpp index 4c15fdfb6..f8fea9c26 100644 --- a/apps/apps_container.cpp +++ b/apps/apps_container.cpp @@ -1,6 +1,7 @@ #include "apps_container.h" #include "global_preferences.h" #include +#include extern "C" { #include @@ -82,8 +83,18 @@ void AppsContainer::suspend(bool checkIfPowerKeyReleased) { } bool AppsContainer::dispatchEvent(Ion::Events::Event event) { - bool alphaLockWantsRedraw = updateAlphaLock(); + jmp_buf jumpEnvironment; + Poincare::TreePool::sharedPool()->setJumpEnvironment(&jumpEnvironment); + int res = setjmp(jumpEnvironment); + if (res != 0) { + // There has been an exception, return an uninitialized node + Poincare::TreePool::sharedPool()->resetJumpEnvironment();// TODO Needed? + switchTo(appSnapshotAtIndex(0)); + //displayMemoryExhaustionPopUp(); TODO + return true; + } + bool alphaLockWantsRedraw = updateAlphaLock(); bool didProcessEvent = false; if (event == Ion::Events::USBEnumeration) { @@ -114,8 +125,10 @@ bool AppsContainer::dispatchEvent(Ion::Events::Event event) { } if (!didProcessEvent && alphaLockWantsRedraw) { window()->redraw(); + Poincare::TreePool::sharedPool()->resetJumpEnvironment(); // TODO Needed? return true; } + Poincare::TreePool::sharedPool()->resetJumpEnvironment(); // TODO Needed? return didProcessEvent || alphaLockWantsRedraw; } diff --git a/escher/src/container.cpp b/escher/src/container.cpp index 0b918de86..4ca3c0357 100644 --- a/escher/src/container.cpp +++ b/escher/src/container.cpp @@ -1,5 +1,6 @@ #include #include +#include Container::Container() : RunLoop(), @@ -36,7 +37,11 @@ App * Container::activeApp() { } bool Container::dispatchEvent(Ion::Events::Event event) { - if (event == Ion::Events::TimerFire || m_activeApp->processEvent(event)) { + if (event == Ion::Events::TimerFire ) { + window()->redraw(); + return true; + } + if (m_activeApp->processEvent(event)) { window()->redraw(); return true; } diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index b9ecdc9e5..0007287c2 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -160,25 +160,27 @@ public: bool isEqualToItsApproximationLayout(Expression approximation, int bufferSize, Preferences::AngleUnit angleUnit, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits, Context & context); /* Layout Helper */ - LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const; + LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { + return node()->createLayout(floatDisplayMode, numberOfSignificantDigits); + } int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode = Preferences::PrintFloatMode::Decimal, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const { return this->node()->serialize(buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits); } /* Simplification */ static Expression ParseAndSimplify(const char * text, Context & context, Preferences::AngleUnit angleUnit); Expression simplify(Context & context, Preferences::AngleUnit angleUnit); - Expression deepReduce(Context & context, Preferences::AngleUnit angleUnit); + Expression deepReduce(Context & context, Preferences::AngleUnit angleUnit); //TODO put private /* Approximation Helper */ template static U epsilon(); template Evaluation approximateToEvaluation(Context& context, Preferences::AngleUnit angleUnit) const { - return node()->approximate(U(), context, angleUnit); + return node()->approximate(U(), context, angleUnit); //TODO put private } template Expression approximate(Context& context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat) const; template U approximateToScalar(Context& context, Preferences::AngleUnit angleUnit) const; template static U approximateToScalar(const char * text, Context& context, Preferences::AngleUnit angleUnit); template U approximateWithValueForSymbol(char symbol, U x, Context & context, Preferences::AngleUnit angleUnit) const; - /* Expression roots/extrema solver*/ + /* Expression roots/extrema solver */ struct Coordinate2D { double abscissa; double value; diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 7ea4015aa..29d627936 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -9,7 +9,6 @@ #include #include #include -#include #include "expression_lexer_parser.h" #include "expression_parser.hpp" @@ -28,19 +27,26 @@ Expression Expression::parse(char const * string) { if (string[0] == 0) { return Expression(); } - YY_BUFFER_STATE buf = poincare_expression_yy_scan_string(string); - jmp_buf jumpEnvironment; - TreePool::sharedPool()->setJumpEnvironment(&jumpEnvironment); - int res = setjmp(jumpEnvironment); - if (res != 0) { - // There has been an exception, return an uninitialized node - TreePool::sharedPool()->resetJumpEnvironment(); - poincare_expression_yylval.expression = Expression(); - poincare_expression_yy_delete_buffer(buf); - return Expression(); - } - Expression expression; + /* The lexer/parser mallocs memory that needs to be freed once the parsing + * finishes, even if the parsing was interrupted by a memory exhaustion + * exception. We thus create another setjmp/lngjmp routine here to catch + * exceptions, delete the malloced memory and restore the previous jump + * environment */ + jmp_buf * previousJumpEnvironment = TreePool::sharedPool()->jumpEnvironment(); + jmp_buf jumpEnvironment; + TreePool::sharedPool()->setJumpEnvironment(&jumpEnvironment); + int res = setjmp(jumpEnvironment); + if (res != 0) { + // There has been an exception. Delete malloced memory and jump. + poincare_expression_yylval.expression = Expression(); + poincare_expression_yy_delete_buffer(buf); + TreePool::sharedPool()->resetJumpEnvironment(); + longjmp(*previousJumpEnvironment, 1); + } + TreePool::sharedPool()->setJumpEnvironment(&jumpEnvironment); + int res = setjmp(jumpEnvironment); YY_BUFFER_STATE buf = poincare_expression_yy_scan_string(string); + Expression expression; if (poincare_expression_yyparse(&expression) != 0) { // Parsing failed because of invalid input or memory exhaustion expression = Expression(); @@ -49,7 +55,7 @@ Expression Expression::parse(char const * string) { * expression alive if only YYVAL refers to it so we reset YYVAL here. */ poincare_expression_yylval.expression = Expression(); poincare_expression_yy_delete_buffer(buf); - TreePool::sharedPool()->resetJumpEnvironment(); + TreePool::sharedPool()->setJumpEnvironment(&previousJumpEnvironment); return expression; } @@ -226,21 +232,6 @@ bool Expression::isEqualToItsApproximationLayout(Expression approximation, int b return equal; } -LayoutRef Expression::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { - jmp_buf jumpEnvironment; - TreePool::sharedPool()->setJumpEnvironment(&jumpEnvironment); - int res = setjmp(jumpEnvironment); - if (res != 0) { - assert(false); - // There has been an exception, return an uninitialized layout - TreePool::sharedPool()->resetJumpEnvironment(); - return LayoutRef(); - } - LayoutRef result = node()->createLayout(floatDisplayMode, numberOfSignificantDigits); - TreePool::sharedPool()->resetJumpEnvironment(); - return result; -} - /* Simplification */ Expression Expression::ParseAndSimplify(const char * text, Context & context, Preferences::AngleUnit angleUnit) { @@ -293,13 +284,13 @@ Expression Expression::deepBeautify(Context & context, Preferences::AngleUnit an template Expression Expression::approximate(Context& context, Preferences::AngleUnit angleUnit, Preferences::Preferences::ComplexFormat complexFormat) const { - Evaluation e = node()->approximate(U(), context, angleUnit); + Evaluation e = node()->approximate(U(), context, angleUnit); //TODO approximateToEval return e.complexToExpression(complexFormat); } template U Expression::approximateToScalar(Context& context, Preferences::AngleUnit angleUnit) const { - Evaluation evaluation = node()->approximate(U(), context, angleUnit); + Evaluation evaluation = node()->approximate(U(), context, angleUnit);//TODO approximateToEval return evaluation.toScalar(); }