Created
August 18, 2018 03:39
-
-
Save Velro/b27723f07b2b12351108251f5b1baf38 to your computer and use it in GitHub Desktop.
Go to next error CLI setup for C++
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
REM This is the file where I compile my whole project | |
REM This outputs the errors into clang_output.log and the terminal. We are forcing clang to output color and with absolute file paths. | |
REM -fcolor-diagnostics and -fansi-escape-codes forces clang to output color codes, which is nice for the console output | |
clang-cl -ferror-limit=10 ^ | |
-fdiagnostics-absolute-paths ^ | |
-fcolor-diagnostics ^ | |
-fansi-escape-codes ^ | |
-fuse-ld=lld-link ^ | |
-o my_program.exe ^ | |
my_program.cpp 2>&1 | tee clang_output.log |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
REM helper batch file I keep at the top-level of my project | |
@echo off | |
compiler/build/project/clang/build.bat | |
REM Reset error indexing util program | |
SET COMPILATION_ERROR_INDEX=0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
REM top level batch to call to open vim to the next error in your project | |
@echo off | |
vim_clang_next_error.exe ^ | |
clang_output.log ^ | |
%COMPILATION_ERROR_INDEX% | |
SET /A COMPILATION_ERROR_INDEX += 1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
int main (int argc, char * argv[]) | |
{ | |
if (argc < 3) /*no command specified*/ | |
{ | |
fprintf(stderr, "Usage: clang_vim_next_error clang_output.log error_number\n"); | |
exit(EXIT_FAILURE); | |
} | |
else | |
{ | |
FILE * fileStream; | |
errno_t fileError = fopen_s(&fileStream, argv[1], "r"); | |
if (fileError != 0) { | |
fprintf(stderr, "Couldn't open file\n"); | |
return 1; | |
} | |
int requestedErrorIndex = atoi(argv[2]); | |
//printf("Requested error index: %d\n", requestedErrorIndex); | |
// obtain file size | |
fseek(fileStream, 0, SEEK_END); | |
long fileSize = ftell(fileStream); | |
rewind(fileStream); | |
// dump file to memory | |
char * file = (char *)calloc(1, sizeof(char)*fileSize); | |
fread(file, 1, fileSize, fileStream); | |
fclose(fileStream); | |
/* An example error with clang-cl. | |
*[1mC:\projects\zah\compiler\code\source\zah_parser.cpp(440,18): [0m[0;1;31merror: [0m[1muse of undeclared identifier 'decl'[0m | |
* TokenToType(&decl->type, typeTok); | |
* | |
* A clang error has a slightly different format, the numbers are given like Ex. file.cpp:440:18: .... | |
*/ | |
// | |
// backslash to forward slash | |
// | |
for (char * ptr = file; ptr < file + fileSize; ++ptr) { | |
if (*ptr == '\\') { | |
*ptr = '/'; | |
} | |
} | |
// | |
// count number of errors | |
// | |
char * errorLocations[512] = {}; | |
int errorCount = 0; | |
char * lastErrorLoc = file; | |
while (true) { | |
char * duh = lastErrorLoc; | |
lastErrorLoc = strstr(duh, "error: "); | |
if (!lastErrorLoc) { | |
break; | |
} | |
errorLocations[errorCount++] = lastErrorLoc; | |
// eat forward so we don't get the same result again | |
lastErrorLoc++; | |
} | |
//printf("Error count: %d", errorCount); | |
// loop to first error if requested index is over count | |
requestedErrorIndex = requestedErrorIndex % errorCount; | |
// | |
// Find requested error and extract info | |
// | |
char * errorLoc = errorLocations[requestedErrorIndex]; | |
char * errorLineNumberStart = nullptr; | |
char * errorColumnNumberStart = nullptr; | |
char filename[512] = {}; | |
// search backwards for line and column number | |
for (char * ptr = errorLoc; errorLoc > file; ptr--) { | |
if (*ptr == ',' && !errorColumnNumberStart) { | |
errorColumnNumberStart = ptr + 1; | |
} | |
if (*ptr == '(' && !errorLineNumberStart) { | |
errorLineNumberStart = ptr + 1; | |
} | |
if (*ptr == '\n') { | |
bool found = false; | |
char * localPtr = ptr + 1; | |
for (localPtr = ptr + 1; localPtr < file + fileSize; ++localPtr) { | |
// sometimes there's a second escape? | |
if (*localPtr == '\x6D' && *(localPtr + 4) != '\x6D') { | |
localPtr++; // eat past escape character | |
char * filenameStart = localPtr; | |
int filenameLength = errorLineNumberStart - filenameStart - 1; | |
memcpy(&filename[0], filenameStart, filenameLength); | |
found = true; | |
break; // inner loop | |
} | |
} | |
if (found) { | |
break; // outer loop | |
} | |
printf("Trouble parsing error\n"); | |
break; | |
} | |
if (ptr == file + 1) { | |
printf("Trouble parsing error\n"); | |
break; | |
} | |
} | |
if (!errorLoc || !errorLineNumberStart || !errorColumnNumberStart) { | |
fprintf(stderr, "Trouble parsing error\n"); | |
return 1; | |
} | |
// | |
// Build vim command | |
// | |
int lineNumber = atoi(errorLineNumberStart); | |
int columnNumber = atoi(errorColumnNumberStart); | |
char buf[512] = {}; | |
snprintf(buf, 512, "gvim --remote-silent \"+call cursor(%d, %d)\" %s", | |
lineNumber, | |
columnNumber, | |
&filename[0]); | |
//puts(buf); | |
// call shell | |
system(buf); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment