mirror of
https://github.com/waku-org/nwaku.git
synced 2025-01-15 17:35:45 +00:00
104 lines
3.4 KiB
Nim
104 lines
3.4 KiB
Nim
import std/os
|
||
import std/osproc
|
||
import std/strutils
|
||
import std/streams
|
||
import std/pegs
|
||
|
||
type
|
||
CompileInfo* = object
|
||
templFile*: string
|
||
errorFile*: string
|
||
errorLine*, errorColumn*: int
|
||
templLine*, templColumn*: int
|
||
msg*: string
|
||
fullMsg*: string
|
||
compileTime*: float
|
||
exitCode*: int
|
||
|
||
let
|
||
# Error pegs, taken from testament tester
|
||
pegLineTemplate =
|
||
peg"{[^(]*} '(' {\d+} ', ' {\d+} ') ' 'template/generic instantiation from here'.*"
|
||
pegLineError =
|
||
peg"{[^(]*} '(' {\d+} ', ' {\d+} ') ' ('Error') ':' \s* {.*}"
|
||
pegOtherError = peg"'Error:' \s* {.*}"
|
||
pegError = pegLineError / pegOtherError
|
||
pegSuccess = peg"'Hint: operation successful' {[^;]*} '; ' {\d+} '.' {\d+} .*"
|
||
|
||
# Timestamp pegs
|
||
# peg for unix timestamp, basically any float with 6 digits after the decimal
|
||
# Not ideal - could also improve by checking for the location in the line
|
||
pegUnixTimestamp = peg"{\d+} '.' {\d\d\d\d\d\d} \s"
|
||
# peg for timestamp with format yyyy-MM-dd HH:mm:sszzz
|
||
pegRfcTimestamp = peg"{\d\d\d\d} '-' {\d\d} '-' {\d\d} ' ' {\d\d} ':' {\d\d} ':' {\d\d} {'+' / '-'} {\d\d} ':' {\d\d} \s"
|
||
# Thread/process id is unpredictable..
|
||
pegXid* = peg"""'tid' (('=') / ('":') / (': [1m') / (': ') / ('[0m=[94m') / ('>')) \d+"""
|
||
|
||
proc cmpIgnorePegs*(a, b: string, pegs: varargs[Peg]): bool =
|
||
## true when input strings are equal without regard to supplied pegs
|
||
var
|
||
aa = a
|
||
bb = b
|
||
for peg in pegs:
|
||
aa = aa.replace(peg, "dummy")
|
||
bb = bb.replace(peg, "dummy")
|
||
result = aa == bb
|
||
|
||
proc cmpIgnoreTimestamp*(a, b: string, timestamp = ""): bool =
|
||
## true when input strings are equal without regard to supplied timestamp form
|
||
if timestamp.len == 0:
|
||
result = cmpIgnorePegs(a, b, pegXid)
|
||
elif timestamp == "RfcTime":
|
||
result = cmpIgnorePegs(a, b, pegRfcTimestamp, pegXid)
|
||
elif timestamp == "UnixTime":
|
||
result = cmpIgnorePegs(a, b, pegUnixTimestamp, pegXid)
|
||
|
||
proc cmpIgnoreDefaultTimestamps*(a, b: string): bool =
|
||
## true when input strings are equal without regard to timestamp
|
||
if cmpIgnorePegs(a, b, pegRfcTimestamp, pegXid):
|
||
result = true
|
||
elif cmpIgnorePegs(a, b, pegUnixTimestamp, pegXid):
|
||
result = true
|
||
|
||
proc parseCompileStream*(p: Process, output: Stream): CompileInfo =
|
||
## parsing compiler output (based on testament tester)
|
||
result.exitCode = -1
|
||
var
|
||
line = newStringOfCap(120).TaintedString
|
||
suc, err, tmpl = ""
|
||
|
||
while true:
|
||
if output.readLine(line):
|
||
if line =~ pegError:
|
||
# `err` should contain the last error/warning message
|
||
err = line
|
||
elif line =~ pegLineTemplate and err == "":
|
||
# `tmpl` contains the last template expansion before the error
|
||
tmpl = line
|
||
elif line =~ pegSuccess:
|
||
suc = line
|
||
|
||
if err != "":
|
||
result.fullMsg.add(line.string & "\p")
|
||
else:
|
||
result.exitCode = peekExitCode(p)
|
||
if result.exitCode != -1:
|
||
break
|
||
|
||
if tmpl =~ pegLineTemplate:
|
||
result.templFile = extractFilename(matches[0])
|
||
result.templLine = parseInt(matches[1])
|
||
result.templColumn = parseInt(matches[2])
|
||
if err =~ pegLineError:
|
||
result.errorFile = extractFilename(matches[0])
|
||
result.errorLine = parseInt(matches[1])
|
||
result.errorColumn = parseInt(matches[2])
|
||
result.msg = matches[3]
|
||
elif err =~ pegOtherError:
|
||
result.msg = matches[0]
|
||
elif suc =~ pegSuccess:
|
||
result.msg = suc
|
||
result.compileTime = parseFloat(matches[1] & "." & matches[2])
|
||
|
||
proc parseExecuteOutput*() = discard
|