scripting engine: replace PrintStdErr with Log; text renderer: syntax highlighting for scripts

This commit is contained in:
nakst 2022-02-12 16:25:25 +00:00
parent 2fcb2878fc
commit 13affeb977
10 changed files with 245 additions and 121 deletions

View File

@ -2,6 +2,11 @@
#include <essence.h>
#include <shared/array.cpp>
// TODO:
// LogOpenGroup()
// LogOpenList()
// LogClose()
struct Instance : EsInstance {
EsCommand commandClearOutput;
@ -27,6 +32,7 @@ struct Instance : EsInstance {
void AddPrompt(Instance *instance);
void AddOutput(Instance *instance, const char *text, size_t textBytes);
void AddLogOutput(Instance *instance, const char *text, size_t textBytes);
// --------------------------------- Script engine interface.
@ -159,19 +165,34 @@ CoroutineState *ExternalCoroutineWaitAny(ExecutionContext *context) {
return nullptr;
}
int ExternalPrintStdErr(ExecutionContext *context, Value *returnValue) {
int ExternalLog(ExecutionContext *context, Value *returnValue) {
(void) returnValue;
STACK_POP_STRING(entryText, entryBytes);
AddOutput(scriptInstance, entryText, entryBytes);
AddLogOutput(scriptInstance, entryText, entryBytes);
return 1;
}
int ExternalPrintStdErrWarning(ExecutionContext *context, Value *returnValue) {
return ExternalPrintStdErr(context, returnValue);
int ExternalTextFormat(ExecutionContext *context, Value *returnValue, const char *mode) {
char *buffer = (char *) EsHeapAllocate(16, false);
uintptr_t index = HeapAllocate(context);
context->heap[index].type = T_STR;
context->heap[index].bytes = EsStringFormat(buffer, 16, "%z", mode);
context->heap[index].text = buffer;
returnValue->i = index;
return 3;
}
int ExternalPrintStdErrHighlight(ExecutionContext *context, Value *returnValue) {
return ExternalPrintStdErr(context, returnValue);
int ExternalTextColorError (ExecutionContext *context, Value *returnValue) { return ExternalTextFormat(context, returnValue, "\a#DB002A]"); }
int ExternalTextColorHighlight(ExecutionContext *context, Value *returnValue) { return ExternalTextFormat(context, returnValue, "\a#362CB6]"); }
int ExternalTextMonospaced (ExecutionContext *context, Value *returnValue) { return ExternalTextFormat(context, returnValue, "\am]"); }
int ExternalTextPlain (ExecutionContext *context, Value *returnValue) { return ExternalTextFormat(context, returnValue, "\a]"); }
int ExternalTextWeight(ExecutionContext *context, Value *returnValue) {
if (context->c->stackPointer < 1) return -1;
int i = context->c->stack[--context->c->stackPointer].i / 100;
if (i < 1) i = 1; else if (i > 9) i = 9;
char b[5] = { '\a', 'w', (char) (i + '0'), ']', 0 };
return ExternalTextFormat(context, returnValue, b);
}
int ExternalSystemSleepMs(ExecutionContext *context, Value *returnValue) {
@ -693,12 +714,19 @@ void AddREPLResult(ExecutionContext *context, EsElement *parent, Node *type, Val
uint64_t pngSignature = 0x0A1A0A0D474E5089;
uint32_t jpgSignature = 0xE0FFD8FF;
bool isPNG = valueBytes > sizeof(pngSignature) && 0 == EsMemoryCompare(&pngSignature, valueText, sizeof(pngSignature));
bool isJPG = valueBytes > sizeof(jpgSignature) && 0 == EsMemoryCompare(&jpgSignature, valueText, sizeof(jpgSignature));
if ((valueBytes > sizeof(pngSignature) && 0 == EsMemoryCompare(&pngSignature, valueText, sizeof(pngSignature)))
|| (valueBytes > sizeof(jpgSignature) && 0 == EsMemoryCompare(&jpgSignature, valueText, sizeof(jpgSignature)))) {
if (isPNG || isJPG) {
EsCanvasPane *canvasPane = EsCanvasPaneCreate(parent, ES_CELL_H_FILL, EsStyleIntern(&styleImageViewerPane));
EsImageDisplay *display = EsImageDisplayCreate(canvasPane, ES_CELL_H_LEFT | ES_CELL_V_TOP);
EsImageDisplayLoadFromMemory(display, valueText, valueBytes);
char *buffer = EsStringAllocateAndFormat(&bytes, "%d by %d pixels \u2027 %z",
EsImageDisplayGetImageWidth(display),
EsImageDisplayGetImageHeight(display),
isPNG ? "PNG" : isJPG ? "JPEG" : "unknown format");
EsTextDisplayCreate(parent, ES_CELL_H_FILL, EsStyleIntern(&styleOutputParagraphItalic), buffer, bytes);
EsHeapFree(buffer);
} else if (EsUTF8IsValid(valueText, valueBytes)) {
char *buffer = EsStringAllocateAndFormat(&bytes, "\u201C%s\u201D", valueBytes, valueText);
EsTextDisplayCreate(parent, ES_CELL_H_FILL, EsStyleIntern(&styleOutputData), buffer, bytes);
@ -858,7 +886,8 @@ void EnterCommand(Instance *instance) {
EsPanel *commandLogRow = EsPanelCreate(instance->root, ES_CELL_H_FILL | ES_PANEL_STACK | ES_PANEL_HORIZONTAL, EsStyleIntern(&styleInputRow));
EsTextDisplayCreate(commandLogRow, ES_FLAGS_DEFAULT, EsStyleIntern(&stylePromptText), "\u2661");
EsTextDisplayCreate(commandLogRow, ES_CELL_H_FILL, EsStyleIntern(&styleCommandLogText), data, dataBytes);
EsTextDisplay *inputCommand = EsTextDisplayCreate(commandLogRow, ES_CELL_H_FILL, EsStyleIntern(&styleCommandLogText), data, dataBytes);
EsTextDisplaySetupSyntaxHighlighting(inputCommand, ES_SYNTAX_HIGHLIGHTING_LANGUAGE_SCRIPT);
instance->outputElements.Add(commandLogRow);
EsAssert(!instance->outputPanel);
@ -891,7 +920,8 @@ void AddOutput(Instance *instance, const char *text, size_t textBytes) {
if (text[i] == '\n') {
if (EsUTF8IsValid(instance->outputLineBuffer, instance->outputLineBufferBytes)) {
EsMessageMutexAcquire();
EsTextDisplayCreate(instance->outputPanel, ES_CELL_H_FILL, EsStyleIntern(&styleOutputParagraph),
EsTextDisplayCreate(instance->outputPanel, ES_CELL_H_FILL | ES_TEXT_DISPLAY_RICH_TEXT,
EsStyleIntern(&styleOutputParagraph),
instance->outputLineBuffer, instance->outputLineBufferBytes);
EsMessageMutexRelease();
} else {
@ -900,6 +930,7 @@ void AddOutput(Instance *instance, const char *text, size_t textBytes) {
EsLiteral("Encoding error.\n"));
EsMessageMutexRelease();
}
instance->outputLineBufferBytes = 0;
} else {
if (instance->outputLineBufferBytes == instance->outputLineBufferAllocated) {
@ -913,6 +944,22 @@ void AddOutput(Instance *instance, const char *text, size_t textBytes) {
}
}
void AddLogOutput(Instance *instance, const char *text, size_t textBytes) {
instance->anyOutput = true;
if (EsUTF8IsValid(text, textBytes)) {
EsMessageMutexAcquire();
EsTextDisplayCreate(instance->outputPanel, ES_CELL_H_FILL | ES_TEXT_DISPLAY_RICH_TEXT,
EsStyleIntern(&styleOutputParagraph), text, textBytes);
EsMessageMutexRelease();
} else {
EsMessageMutexAcquire();
EsTextDisplayCreate(instance->outputPanel, ES_CELL_H_FILL,
EsStyleIntern(&styleOutputParagraphItalic), EsLiteral("Encoding error.\n"));
EsMessageMutexRelease();
}
}
void AddPrompt(Instance *instance) {
if (instance->outputPanel) {
instance->outputElements.Add(EsElementGetLayoutParent(instance->outputPanel));
@ -928,6 +975,7 @@ void AddPrompt(Instance *instance) {
instance->inputRow = EsPanelCreate(instance->root, ES_CELL_H_FILL | ES_PANEL_STACK | ES_PANEL_HORIZONTAL, EsStyleIntern(&styleInputRow));
EsTextDisplayCreate(instance->inputRow, ES_FLAGS_DEFAULT, EsStyleIntern(&stylePromptText), "\u2665");
instance->inputTextbox = EsTextboxCreate(instance->inputRow, ES_CELL_H_FILL, EsStyleIntern(&styleInputTextbox));
EsTextboxSetupSyntaxHighlighting(instance->inputTextbox, ES_SYNTAX_HIGHLIGHTING_LANGUAGE_SCRIPT);
EsTextboxEnableSmartReplacement(instance->inputTextbox, false);
instance->inputTextbox->messageUser = InputTextboxMessage;
EsElementFocus(instance->inputTextbox, ES_ELEMENT_FOCUS_ENSURE_VISIBLE);

View File

@ -5822,6 +5822,14 @@ int ProcessImageDisplayMessage(EsElement *element, EsMessage *message) {
return 0;
}
uint32_t EsImageDisplayGetImageWidth(EsImageDisplay *display) {
return display->width;
}
uint32_t EsImageDisplayGetImageHeight(EsImageDisplay *display) {
return display->height;
}
EsImageDisplay *EsImageDisplayCreate(EsElement *parent, uint64_t flags, EsStyleID style) {
EsImageDisplay *display = (EsImageDisplay *) EsHeapAllocate(sizeof(EsImageDisplay), true);
if (!display) return nullptr;

View File

@ -694,8 +694,9 @@ define ES_ELEMENT_TRANSITION_HIDE_AFTER_COMPLETE (1 << 2)
define ES_TEXT_GET_CHARACTER_AT_POINT_MIDDLE (1 << 0)
define ES_SYNTAX_HIGHLIGHTING_LANGUAGE_C (1)
define ES_SYNTAX_HIGHLIGHTING_LANGUAGE_INI (2)
define ES_SYNTAX_HIGHLIGHTING_LANGUAGE_C (1)
define ES_SYNTAX_HIGHLIGHTING_LANGUAGE_INI (2)
define ES_SYNTAX_HIGHLIGHTING_LANGUAGE_SCRIPT (3)
define ES_DRAW_LINE_CAP_ROUND (1 << 0)
define ES_DRAW_LINE_CAP_SQUARE (1 << 1)
@ -2569,6 +2570,8 @@ function EsImageDisplay *EsImageDisplayCreate(EsElement *parent, uint64_t flags
function void EsImageDisplayLoadBits(EsImageDisplay *display, const uint32_t *bits, size_t width, size_t height, size_t stride) @matrix_in(bits, width, height);
function void EsImageDisplayLoadFromMemory(EsImageDisplay *display, const void *buffer, size_t bufferBytes) @buffer_in(buffer, bufferBytes);
function void EsImageDisplayPaint(EsImageDisplay *display, EsPainter *painter, EsRectangle bounds);
function uint32_t EsImageDisplayGetImageWidth(EsImageDisplay *display);
function uint32_t EsImageDisplayGetImageHeight(EsImageDisplay *display);
function EsTextDisplay *EsTextDisplayCreate(EsElement *parent, uint64_t flags = ES_FLAGS_DEFAULT, EsStyleID style = 0, STRING label = BLANK_STRING);
function void EsTextDisplaySetContents(EsTextDisplay *display, STRING contents = BLANK_STRING);

View File

@ -2548,6 +2548,9 @@ void EsDrawTextThemed(EsPainter *painter, EsElement *element, EsRectangle bounds
void EsRichTextParse(const char *inString, ptrdiff_t inStringBytes,
char **outString, EsTextRun **outTextRuns, size_t *outTextRunCount,
EsTextStyle *baseStyle) {
// TODO Check that this can be used on untrusted input.
// Specifically, what if textRunCount/stringBytes are calculated incorrectly?
if (inStringBytes == -1) {
inStringBytes = EsCStringLength(inString);
}
@ -2597,15 +2600,17 @@ void EsRichTextParse(const char *inString, ptrdiff_t inStringBytes,
if (c == ']') {
break;
} else if (c == 'w' /* weight */) {
i++; if (i >= inStringBytes || inString[i] == ']') goto parsedFormat;
textRun->style.font.weight = inString[i] - '0';
i++;
if (i >= inStringBytes || inString[i] == ']') {}
else textRun->style.font.weight = inString[i] - '0';
} else if (c == 'i' /* italic */) {
textRun->style.font.flags |= ES_FONT_ITALIC;
} else if (c == 's' /* size */) {
textRun->style.size = 0;
while (true) {
i++; if (i >= inStringBytes || inString[i] == ']') goto parsedFormat;
i++;
if (i >= inStringBytes || inString[i] == ']') break;
if (inString[i] < '0' || inString[i] > '9') { i--; break; }
textRun->style.size *= 10;
textRun->style.size += inString[i] - '0';
@ -2627,12 +2632,11 @@ void EsRichTextParse(const char *inString, ptrdiff_t inStringBytes,
string[bytes++] = inString[i++];
}
i--;
textRun->style.color = EsColorParse(string, bytes);
goto parsedFormat;
}
}
parsedFormat:;
textRunIndex++;
} else {
string[stringIndex++] = inString[i];
@ -2650,41 +2654,84 @@ void EsRichTextParse(const char *inString, ptrdiff_t inStringBytes,
// --------------------------------- Syntax highlighting.
const char *const keywords_a[] = { "auto", nullptr };
const char *const keywords_b[] = { "bool", "break", nullptr };
const char *const keywords_c[] = { "case", "char", "const", "continue", nullptr };
const char *const keywords_d[] = { "default", "do", "double", nullptr };
const char *const keywords_e[] = { "else", "enum", "extern", nullptr };
const char *const keywords_f[] = { "float", "for", nullptr };
const char *const keywords_g[] = { "goto", nullptr };
const char *const keywords_h[] = { nullptr };
const char *const keywords_i[] = { "if", "inline", "int", "int16_t", "int32_t", "int64_t", "int8_t", "intptr_t", nullptr };
const char *const keywords_j[] = { nullptr };
const char *const keywords_k[] = { nullptr };
const char *const keywords_l[] = { "long", nullptr };
const char *const keywords_m[] = { nullptr };
const char *const keywords_n[] = { nullptr };
const char *const keywords_o[] = { nullptr };
const char *const keywords_p[] = { nullptr };
const char *const keywords_q[] = { nullptr };
const char *const keywords_r[] = { "register", "restrict", "return", nullptr };
const char *const keywords_s[] = { "short", "signed", "sizeof", "static", "struct", "switch", nullptr };
const char *const keywords_t[] = { "typedef", nullptr };
const char *const keywords_u[] = { "uint16_t", "uint32_t", "uint64_t", "uint8_t", "uintptr_t", "union", "unsigned", nullptr };
const char *const keywords_v[] = { "void", "volatile", nullptr };
const char *const keywords_w[] = { "while", nullptr };
const char *const keywords_x[] = { nullptr };
const char *const keywords_y[] = { nullptr };
const char *const keywords_z[] = { nullptr };
const char *const keywordsC_a[] = { "auto", nullptr };
const char *const keywordsC_b[] = { "bool", "break", nullptr };
const char *const keywordsC_c[] = { "case", "char", "const", "continue", nullptr };
const char *const keywordsC_d[] = { "default", "do", "double", nullptr };
const char *const keywordsC_e[] = { "else", "enum", "extern", nullptr };
const char *const keywordsC_f[] = { "float", "for", nullptr };
const char *const keywordsC_g[] = { "goto", nullptr };
const char *const keywordsC_h[] = { nullptr };
const char *const keywordsC_i[] = { "if", "inline", "int", "int16_t", "int32_t", "int64_t", "int8_t", "intptr_t", nullptr };
const char *const keywordsC_j[] = { nullptr };
const char *const keywordsC_k[] = { nullptr };
const char *const keywordsC_l[] = { "long", nullptr };
const char *const keywordsC_m[] = { nullptr };
const char *const keywordsC_n[] = { nullptr };
const char *const keywordsC_o[] = { nullptr };
const char *const keywordsC_p[] = { nullptr };
const char *const keywordsC_q[] = { nullptr };
const char *const keywordsC_r[] = { "register", "restrict", "return", nullptr };
const char *const keywordsC_s[] = { "short", "signed", "sizeof", "static", "struct", "switch", nullptr };
const char *const keywordsC_t[] = { "typedef", nullptr };
const char *const keywordsC_u[] = { "uint16_t", "uint32_t", "uint64_t", "uint8_t", "uintptr_t", "union", "unsigned", nullptr };
const char *const keywordsC_v[] = { "void", "volatile", nullptr };
const char *const keywordsC_w[] = { "while", nullptr };
const char *const keywordsC_x[] = { nullptr };
const char *const keywordsC_y[] = { nullptr };
const char *const keywordsC_z[] = { nullptr };
const char *const *const keywords[] = {
keywords_a, keywords_b, keywords_c, keywords_d,
keywords_e, keywords_f, keywords_g, keywords_h,
keywords_i, keywords_j, keywords_k, keywords_l,
keywords_m, keywords_n, keywords_o, keywords_p,
keywords_q, keywords_r, keywords_s, keywords_t,
keywords_u, keywords_v, keywords_w, keywords_x,
keywords_y, keywords_z,
const char *const keywordsScript_a[] = { "assert", "await", nullptr };
const char *const keywordsScript_b[] = { "bool", nullptr };
const char *const keywordsScript_c[] = { nullptr };
const char *const keywordsScript_d[] = { nullptr };
const char *const keywordsScript_e[] = { "else", nullptr };
const char *const keywordsScript_f[] = { "false", "float", "for", "functype", nullptr };
const char *const keywordsScript_g[] = { nullptr };
const char *const keywordsScript_h[] = { nullptr };
const char *const keywordsScript_i[] = { "if", "int", nullptr };
const char *const keywordsScript_j[] = { nullptr };
const char *const keywordsScript_k[] = { nullptr };
const char *const keywordsScript_l[] = { nullptr };
const char *const keywordsScript_m[] = { nullptr };
const char *const keywordsScript_n[] = { "new", "null", nullptr };
const char *const keywordsScript_o[] = { nullptr };
const char *const keywordsScript_p[] = { nullptr };
const char *const keywordsScript_q[] = { nullptr };
const char *const keywordsScript_r[] = { "return", nullptr };
const char *const keywordsScript_s[] = { "str", "struct", nullptr };
const char *const keywordsScript_t[] = { "true", "tuple", nullptr };
const char *const keywordsScript_u[] = { nullptr };
const char *const keywordsScript_v[] = { "void", nullptr };
const char *const keywordsScript_w[] = { "while", nullptr };
const char *const keywordsScript_x[] = { nullptr };
const char *const keywordsScript_y[] = { nullptr };
const char *const keywordsScript_z[] = { nullptr };
const char *const *const keywordsC[] = {
keywordsC_a, keywordsC_b, keywordsC_c, keywordsC_d,
keywordsC_e, keywordsC_f, keywordsC_g, keywordsC_h,
keywordsC_i, keywordsC_j, keywordsC_k, keywordsC_l,
keywordsC_m, keywordsC_n, keywordsC_o, keywordsC_p,
keywordsC_q, keywordsC_r, keywordsC_s, keywordsC_t,
keywordsC_u, keywordsC_v, keywordsC_w, keywordsC_x,
keywordsC_y, keywordsC_z,
};
const char *const *const keywordsScript[] = {
keywordsScript_a, keywordsScript_b, keywordsScript_c, keywordsScript_d,
keywordsScript_e, keywordsScript_f, keywordsScript_g, keywordsScript_h,
keywordsScript_i, keywordsScript_j, keywordsScript_k, keywordsScript_l,
keywordsScript_m, keywordsScript_n, keywordsScript_o, keywordsScript_p,
keywordsScript_q, keywordsScript_r, keywordsScript_s, keywordsScript_t,
keywordsScript_u, keywordsScript_v, keywordsScript_w, keywordsScript_x,
keywordsScript_y, keywordsScript_z,
};
const char *const *const *const keywords[] = {
keywordsC,
nullptr /* INI */,
keywordsScript,
};
bool CharIsAlphaOrDigitOrUnderscore(char c) {
@ -2693,7 +2740,6 @@ bool CharIsAlphaOrDigitOrUnderscore(char c) {
Array<EsTextRun> TextApplySyntaxHighlighting(const EsTextStyle *baseStyle, int language, uint32_t *colors, Array<EsTextRun> runs, const char *string, size_t bytes) {
// TODO Make these colors customizable!
// TODO Highlight keywords.
int lexState = 0;
bool inComment = false, inIdentifier = false, inChar = false, startedString = false;
@ -2713,14 +2759,14 @@ Array<EsTextRun> TextApplySyntaxHighlighting(const EsTextStyle *baseStyle, int l
last = 0;
}
if (language == ES_SYNTAX_HIGHLIGHTING_LANGUAGE_C) {
if (language == ES_SYNTAX_HIGHLIGHTING_LANGUAGE_C || language == ES_SYNTAX_HIGHLIGHTING_LANGUAGE_SCRIPT) {
if (lexState == 4) {
lexState = 0;
} else if (lexState == 1) {
if ((last & 0xFF0000) == ('*' << 16) && (last & 0xFF00) == ('/' << 8) && inComment) {
lexState = 0, inComment = false;
}
} else if (lexState == 3 || lexState == 6) {
} else if (lexState == 3 || lexState == 6 || (lexState == 5 && language == ES_SYNTAX_HIGHLIGHTING_LANGUAGE_SCRIPT)) {
if (!CharIsAlphaOrDigitOrUnderscore(c)) {
lexState = 0;
}
@ -2760,7 +2806,7 @@ Array<EsTextRun> TextApplySyntaxHighlighting(const EsTextStyle *baseStyle, int l
inIdentifier = true;
if (c >= 'a' && c <= 'z' && (!index || !CharIsAlphaOrDigitOrUnderscore(string[index - 1]))) {
const char *const *k = keywords[c - 'a'];
const char *const *k = keywords[language - 1][c - 'a'];
for (int i = 0; k[i]; i++) {
int j = 0;

View File

@ -170,14 +170,14 @@ void PortMesa() {
void PortGCC() {
if buildCross {
// Print instructions.
PrintStdErr("To build Essence, you need a cross compiler. This will be built for you automatically.\n");
PrintStdErr("- You need to be connected to the internet. ~100MB will be downloaded.\n");
PrintStdErr("- You need ~3GB of drive space available.\n");
PrintStdErr("- You need ~8GB of RAM available.\n");
PrintStdErr("- This should take ~20 minutes on a modern computer.\n");
PrintStdErr("- This does *not* require root permissions.\n");
PrintStdErr("- You must fully update your system before building.\n");
PrintStdErr("Enter 'yes' to continue.\n");
Log("To build Essence, you need a cross compiler. This will be built for you automatically.");
Log("- You need to be connected to the internet. ~100MB will be downloaded.");
Log("- You need ~3GB of drive space available.");
Log("- You need ~8GB of RAM available.");
Log("- This should take ~20 minutes on a modern computer.");
Log("- This does *not* require root permissions.");
Log("- You must fully update your system before building.");
Log("Enter 'yes' to continue.");
assert ConsoleGetYes();
}
@ -234,8 +234,8 @@ void PortGCC() {
// Ask the user if they want to resume an incomplete build.
bool resumeBuild = false;
if runningMakefiles {
PrintStdErr("The build system has detected a build was started, but was not completed.\n");
PrintStdErr("Enter 'yes' to attempt to resume this build.\n");
Log("The build system has detected a build was started, but was not completed.");
Log("Enter 'yes' to attempt to resume this build.");
resumeBuild = ConsoleGetYes();
runningMakefiles = false;
}
@ -429,7 +429,7 @@ void PortGCC() {
PathDeleteRecursively("bin/mpc-src");
PathDeleteRecursively("bin/mpfr-src");
PathDeleteRecursively("bin/gmp-src");
PrintStdErrHighlight("Build succeeded.\n");
LogInfo("Build succeeded.");
}
void PortFreeType() {
@ -618,24 +618,24 @@ void Start() {
PortCallback[] portCallbacks = [ PortFFmpeg, PortUxn, PortNasm, PortBochs, PortBusybox, PortMesa, PortGCC, PortFreeType, PortHarfBuzz, PortMusl ];
if portName == "" {
PrintStdErrHighlight("Available ports:\n");
LogInfo("Available ports:");
for int i = 0; i < portNames:len(); i += 1 {
PrintStdErr("\t%portNames[i]%\n");
Log("\t%portNames[i]%");
}
} else {
assert targetName != "";
assert toolchainPrefix != "";
// PrintStdErrHighlight("Target name: '%targetName%'\n");
// PrintStdErrHighlight("Toolchain prefix: '%toolchainPrefix%'\n");
// PrintStdErrHighlight("Processors to use for compilation: '%processorCount%'\n");
// PrintStdErrHighlight("Skip yes checks: '%skipYesChecks%'\n");
// LogInfo("Target name: '%targetName%'");
// LogInfo("Toolchain prefix: '%toolchainPrefix%'");
// LogInfo("Processors to use for compilation: '%processorCount%'");
// LogInfo("Skip yes checks: '%skipYesChecks%'");
for int i = 0; i < portNames:len(); i += 1 {
if portNames[i] == portName || portName == "all" {
if portName == "all" {
PrintStdErrHighlight("Building port: '%portNames[i]%'\n");
LogInfo("Building port: '%portNames[i]%'");
}
portCallbacks[i]();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 426 KiB

After

Width:  |  Height:  |  Size: 426 KiB

View File

@ -456,6 +456,7 @@ _EsUISetFont=454
EsWorkQueue=455
EsWorkIsExiting=456
EsPanelRadioGroupGetChecked=457
EsImageDisplayGetImageWidth=458
EsBufferWriteInt8=459
EsInstanceGetStartupRequest=460
EsImageDisplayPaint=461
@ -492,3 +493,4 @@ _EsDebugCommand=491
DateToLinear=492
EsRectangleContainsAll=493
EsListViewFixedItemSetEnumStringsForColumn=494
EsImageDisplayGetImageHeight=495

View File

@ -25,9 +25,9 @@ void Get(str url, str directoryName, str checksum) {
if checksum != "" {
// If we're verifying the checksum of the file, then it should be okay to try downloading it from a non-official mirror.
alternateURL = "https://github.com/nakst/cdn/raw/main/cache/" + url2;
PrintStdErr("Attempting to download from '%alternateURL%' with fallback '%url%'...\n");
Log("Attempting to download from '%alternateURL%' with fallback '%url%'...");
} else {
PrintStdErr("Attempting to download from '%url%'...\n");
Log("Attempting to download from '%url%'...");
}
bool got = PathExists(cachePath);
@ -37,18 +37,18 @@ void Get(str url, str directoryName, str checksum) {
if !got {
PathDelete(cachePath);
PrintStdErrWarning("Error: Could not download the file at '%url%'. Exiting.\n");
LogError("Could not download the file at '%url%'. Exiting.\n");
assert false;
}
if checksum != "" {
if SystemShellEvaluate("shasum -a 256 %cachePath%") != "%checksum% %cachePath%\n" {
PrintStdErrWarning("Error: Checksum mismatch for file '%cachePath%'.\n");
LogError("Checksum mismatch for file '%cachePath%'.\n");
PathDelete(cachePath);
assert false;
}
PrintStdErr("Valid checksum.\n");
Log("Valid checksum.");
}
str decompressFlag = "";
@ -60,14 +60,14 @@ void Get(str url, str directoryName, str checksum) {
} else if StringContains(url, ".tar.gz") {
decompressFlag = "z";
} else {
PrintStdErrWarning("Error: Unrecognised archive format extension.\n");
LogError("Unrecognised archive format extension.\n");
assert false;
}
assert SystemShellExecute("tar -x%decompressFlag%f %cachePath%");
assert PathMove(directoryName, "bin/source");
PrintStdErr("File successfully downloaded and extracted.\n");
Log("File successfully downloaded and extracted.");
}
void Start() {

View File

@ -437,9 +437,16 @@ char baseModuleSource[] = {
// Logging:
"void PrintStdErr(str x) #extcall;"
"void PrintStdErrWarning(str x) #extcall;"
"void PrintStdErrHighlight(str x) #extcall;"
"void Log(str x) #extcall;"
"void LogInfo(str x) { Log(TextColorHighlight() + x); }"
"void LogError(str x) { Log(TextColorError() + \"Error: \" + x); }"
"str TextColorError() #extcall;"
"str TextColorHighlight() #extcall;"
"str TextWeight(int i) #extcall;"
"str TextMonospaced() #extcall;"
"str TextPlain() #extcall;"
"str TextBold() { return TextWeight(700); }"
// String operations:
@ -691,9 +698,12 @@ char baseModuleSource[] = {
// --------------------------------- External function calls.
int ExternalPrintStdErr(ExecutionContext *context, Value *returnValue);
int ExternalPrintStdErrWarning(ExecutionContext *context, Value *returnValue);
int ExternalPrintStdErrHighlight(ExecutionContext *context, Value *returnValue);
int ExternalLog(ExecutionContext *context, Value *returnValue);
int ExternalTextColorError(ExecutionContext *context, Value *returnValue);
int ExternalTextColorHighlight(ExecutionContext *context, Value *returnValue);
int ExternalTextWeight(ExecutionContext *context, Value *returnValue);
int ExternalTextMonospaced(ExecutionContext *context, Value *returnValue);
int ExternalTextPlain(ExecutionContext *context, Value *returnValue);
int ExternalConsoleGetLine(ExecutionContext *context, Value *returnValue);
int ExternalStringSlice(ExecutionContext *context, Value *returnValue);
int ExternalCharacterToByte(ExecutionContext *context, Value *returnValue);
@ -730,9 +740,12 @@ int External_DirectoryInternalEndIteration(ExecutionContext *context, Value *ret
int ExternalOpenDocumentEnumerate(ExecutionContext *context, Value *returnValue);
ExternalFunction externalFunctions[] = {
{ .cName = "PrintStdErr", .callback = ExternalPrintStdErr },
{ .cName = "PrintStdErrWarning", .callback = ExternalPrintStdErrWarning },
{ .cName = "PrintStdErrHighlight", .callback = ExternalPrintStdErrHighlight },
{ .cName = "Log", .callback = ExternalLog },
{ .cName = "TextColorError", .callback = ExternalTextColorError },
{ .cName = "TextColorHighlight", .callback = ExternalTextColorHighlight },
{ .cName = "TextWeight", .callback = ExternalTextWeight },
{ .cName = "TextMonospaced", .callback = ExternalTextMonospaced },
{ .cName = "TextPlain", .callback = ExternalTextPlain },
{ .cName = "ConsoleGetLine", .callback = ExternalConsoleGetLine },
{ .cName = "StringSlice", .callback = ExternalStringSlice },
{ .cName = "CharacterToByte", .callback = ExternalCharacterToByte },
@ -5363,6 +5376,7 @@ pthread_mutex_t externalCoroutineMutex;
CoroutineState *externalCoroutineUnblockedList;
bool systemShellLoggingEnabled = true;
bool coloredOutput;
char *scriptSourceDirectory;
@ -5552,33 +5566,36 @@ int ExternalSystemShellEnableLogging(ExecutionContext *context, Value *returnVal
return 1;
}
int ExternalPrintStdErr(ExecutionContext *context, Value *returnValue) {
(void) returnValue;
int ExternalLog(ExecutionContext *context, Value *returnValue) {
STACK_POP_STRING(entryText, entryBytes);
fprintf(stderr, "%.*s", (int) entryBytes, (char *) entryText);
fprintf(stderr, coloredOutput ? "\033[0;m\n" : "\n");
return 1;
}
int ExternalPrintStdErrWarning(ExecutionContext *context, Value *returnValue) {
(void) returnValue;
STACK_POP_STRING(entryText, entryBytes);
static int coloredOutput = 0;
#ifndef _WIN32
if (!coloredOutput) coloredOutput = isatty(STDERR_FILENO) ? 2 : 1;
#endif
fprintf(stderr, coloredOutput == 2 ? "\033[0;33m%.*s\033[0;m" : "%.*s", (int) entryBytes, (char *) entryText);
return 1;
int ExternalTextFormat(ExecutionContext *context, Value *returnValue, const char *mode) {
if (coloredOutput) {
char *buffer = malloc(32);
uintptr_t index = HeapAllocate(context);
context->heap[index].type = T_STR;
context->heap[index].bytes = sprintf(buffer, "\033[0;%sm", mode);
context->heap[index].text = buffer;
returnValue->i = index;
} else {
returnValue->i = 0;
}
return 3;
}
int ExternalPrintStdErrHighlight(ExecutionContext *context, Value *returnValue) {
(void) returnValue;
STACK_POP_STRING(entryText, entryBytes);
static int coloredOutput = 0;
#ifndef _WIN32
if (!coloredOutput) coloredOutput = isatty(STDERR_FILENO) ? 2 : 1;
#endif
fprintf(stderr, coloredOutput == 2 ? "\033[0;36m%.*s\033[0;m" : "%.*s", (int) entryBytes, (char *) entryText);
return 1;
int ExternalTextColorError (ExecutionContext *context, Value *returnValue) { return ExternalTextFormat(context, returnValue, "31"); }
int ExternalTextColorHighlight(ExecutionContext *context, Value *returnValue) { return ExternalTextFormat(context, returnValue, "36"); }
int ExternalTextMonospaced (ExecutionContext *context, Value *returnValue) { return ExternalTextFormat(context, returnValue, ""); }
int ExternalTextPlain (ExecutionContext *context, Value *returnValue) { return ExternalTextFormat(context, returnValue, ""); }
int ExternalTextWeight(ExecutionContext *context, Value *returnValue) {
if (context->c->stackPointer < 1) return -1;
return ExternalTextFormat(context, returnValue, context->c->stack[--context->c->stackPointer].i > 500 ? "1" : "");
}
int ExternalPathCreateDirectory(ExecutionContext *context, Value *returnValue) {
@ -6240,8 +6257,8 @@ int main(int argc, char **argv) {
return 1;
}
coloredOutput = isatty(STDERR_FILENO);
srand(time(NULL));
sem_init(&externalCoroutineSemaphore, 0, 0);
char *scriptPath = NULL;

View File

@ -13,28 +13,28 @@ void Setup(bool forAutomation) {
assert PathCreateLeadingDirectories("bin/Object Files");
if SystemGetHostName() == "Cygwin" {
PrintStdErrWarning("Building on Cygwin is not supported. Use the Windows Subsystem for Linux instead.\n");
LogError("Building on Cygwin is not supported. Use the Windows Subsystem for Linux instead.");
assert false;
}
if SystemShellEvaluate("shasum -a 256 util/test.txt")
!= "2c5622dbbf2552e0e66424a302bde0918e09379afce47eef1a21ef0198990fed util/test.txt\n" {
PrintStdErrWarning("--------------------------------------------------------------------\n");
PrintStdErrWarning(" The source has been corrupted!! \n");
PrintStdErrWarning(" Please check that you have disabled any automatic line-ending or \n");
PrintStdErrWarning(" encoding conversions in Git and archive extraction tools you use. \n");
PrintStdErrWarning("--------------------------------------------------------------------\n");
Log(TextColorError() + "--------------------------------------------------------------------");
Log(TextColorError() + " The source has been corrupted!! ");
Log(TextColorError() + " Please check that you have disabled any automatic line-ending or ");
Log(TextColorError() + " encoding conversions in Git and archive extraction tools you use. ");
Log(TextColorError() + "--------------------------------------------------------------------");
assert false;
}
if StringContains(PathGetDefaultPrefix(), " ") {
PrintStdErrWarning("Error: The path to your essence directory, '%PathGetDefaultPrefix()%', contains spaces.\n");
LogError("The path to your essence directory, '%PathGetDefaultPrefix()%', contains spaces.");
assert false;
}
if !SystemShellExecute("which gcc > /dev/null") { PrintStdErrWarning("Error: GCC was not found.\n"); assert false; }
if !SystemShellExecute("which nasm > /dev/null") { PrintStdErrWarning("Error: Nasm was not found.\n"); assert false; }
if !SystemShellExecute("which make > /dev/null") { PrintStdErrWarning("Error: Make was not found.\n"); assert false; }
if !SystemShellExecute("which gcc > /dev/null") { LogError("GCC was not found."); assert false; }
if !SystemShellExecute("which nasm > /dev/null") { LogError("Nasm was not found."); assert false; }
if !SystemShellExecute("which make > /dev/null") { LogError("Make was not found."); assert false; }
if target == "" {
target = "TARGET_X86_64";
@ -54,7 +54,7 @@ void Setup(bool forAutomation) {
void Start() {
Setup(false);
SystemShellExecute("bin/build %options%");
PrintStdErrHighlight("\n");
Log("");
}
void GenerateOVF() {