/** Helper function for Error(), Warning(), etc. @param type The type of message being printed (e.g. "Warning") @param p Position in source file that is connected to the message being printed @param fmt printf()-style format string @param args Arguments with values for format string % entries */ static void lPrint(const char *type, bool isError, SourcePos p, const char *fmt, va_list args) { char *errorBuf, *formattedBuf; if (vasprintf(&errorBuf, fmt, args) == -1) { fprintf(stderr, "vasprintf() unable to allocate memory!\n"); abort(); } int indent = 0; if (p.first_line == 0) { // We don't have a valid SourcePos, so create a message without it if (asprintf(&formattedBuf, "%s%s%s%s%s: %s%s", lStartBold(), isError ? lStartRed() : lStartBlue(), type, lResetColor(), lStartBold(), errorBuf, lResetColor()) == -1) { fprintf(stderr, "asprintf() unable to allocate memory!\n"); exit(1); } indent = lFindIndent(1, formattedBuf); } else { // Create an error message that includes the file and line number if (asprintf(&formattedBuf, "%s%s:%d:%d: %s%s%s%s: %s%s", lStartBold(), p.name, p.first_line, p.first_column, isError ? lStartRed() : lStartBlue(), type, lResetColor(), lStartBold(), errorBuf, lResetColor()) == -1) { fprintf(stderr, "asprintf() unable to allocate memory!\n"); exit(1); } indent = lFindIndent(3, formattedBuf); } // Don't indent too much with long filenames indent = std::min(indent, 8); // Now that we've done all that work, see if we've already printed the // exact same error message. If so, return, so we don't redundantly // print it and annoy the user. static std::set<std::string> printed; if (printed.find(formattedBuf) != printed.end()) return; printed.insert(formattedBuf); lPrintWithWordBreaks(formattedBuf, indent, lTerminalWidth(), stderr); lPrintFileLineContext(p); free(errorBuf); free(formattedBuf); }
/** Helper function for Error(), Warning(), etc. @param type The type of message being printed (e.g. "Warning") @param p Position in source file that is connected to the message being printed @param fmt printf()-style format string @param args Arguments with values for format string % entries */ static void lPrint(const char *type, SourcePos p, const char *fmt, va_list args) { #ifdef ISPC_IS_WINDOWS char errorBuf[2048], formattedBuf[2048]; if (vsnprintf_s(errorBuf, sizeof(errorBuf), _TRUNCATE, fmt, args) == -1) { fprintf(stderr, "vsnprintf_s() error!\n"); return; } if (p.first_line == 0) { // We don't have a valid SourcePos, so create a message without it if (sprintf_s(formattedBuf, sizeof(formattedBuf), "%s: %s\n", type, errorBuf) == -1) { fprintf(stderr, "vsnprintf_s() error!\n"); exit(1); } } else { // Create an error message that includes the file and line number if (sprintf_s(formattedBuf, sizeof(formattedBuf), "%s(%d): %s: %s\n", p.name, p.first_line, type, errorBuf) == -1) { fprintf(stderr, "vsnprintf_s() error!\n"); exit(1); } } #else char *errorBuf, *formattedBuf; if (vasprintf(&errorBuf, fmt, args) == -1) { fprintf(stderr, "vasprintf() unable to allocate memory!\n"); abort(); } if (p.first_line == 0) { // We don't have a valid SourcePos, so create a message without it if (asprintf(&formattedBuf, "%s: %s\n", type, errorBuf) == -1) { fprintf(stderr, "asprintf() unable to allocate memory!\n"); exit(1); } } else { // Create an error message that includes the file and line number if (asprintf(&formattedBuf, "%s:%d:%d: %s: %s\n", p.name, p.first_line, p.first_column, type, errorBuf) == -1) { fprintf(stderr, "asprintf() unable to allocate memory!\n"); exit(1); } } #endif // Now that we've done all that work, see if we've already printed the // exact same error message. If so, return, so we don't redundantly // print it and annoy the user. static std::set<std::string> printed; if (printed.find(formattedBuf) != printed.end()) return; printed.insert(formattedBuf); lPrintWithWordBreaks(formattedBuf, lTerminalWidth(), stderr); lPrintFileLineContext(p); #ifndef ISPC_IS_WINDOWS free(errorBuf); free(formattedBuf); #endif // !ISPC_IS_WINDOWS }