Index: experimental/webtry/webtry.go |
diff --git a/experimental/webtry/webtry.go b/experimental/webtry/webtry.go |
index e644d138a71a26c3409e825d8706538e9fc8ffcc..e09e611264feb5b43b36c0f9fa59410f3ee3ee95 100644 |
--- a/experimental/webtry/webtry.go |
+++ b/experimental/webtry/webtry.go |
@@ -23,6 +23,7 @@ import ( |
"os/exec" |
"path/filepath" |
"regexp" |
+ "strconv" |
"strings" |
"text/template" |
"time" |
@@ -404,10 +405,10 @@ func expandGyp(hash string) error { |
// response is serialized to JSON as a response to POSTs. |
type response struct { |
- Message string `json:"message"` |
- StdOut string `json:"stdout"` |
- Img string `json:"img"` |
- Hash string `json:"hash"` |
+ Message string `json:"message"` |
+ CompileErrors []compileError `json:"compileErrors"` |
+ Img string `json:"img"` |
+ Hash string `json:"hash"` |
} |
// doCmd executes the given command line string; the command being |
@@ -446,6 +447,23 @@ func reportTryError(w http.ResponseWriter, r *http.Request, err error, message, |
} |
log.Printf("Error: %s\n%s", message, err.Error()) |
resp, err := json.Marshal(m) |
+ |
+ if err != nil { |
+ http.Error(w, "Failed to serialize a response", 500) |
+ return |
+ } |
+ w.Header().Set("Content-Type", "text/plain") |
+ w.Write(resp) |
+} |
+ |
+func reportCompileError(w http.ResponseWriter, r *http.Request, compileErrors []compileError, hash string) { |
+ m := response{ |
+ CompileErrors: compileErrors, |
+ Hash: hash, |
+ } |
+ |
+ resp, err := json.Marshal(m) |
+ |
if err != nil { |
http.Error(w, "Failed to serialize a response", 500) |
return |
@@ -792,6 +810,12 @@ func cleanCompileOutput(s, hash string) string { |
return strings.Replace(s, old, "usercode.cpp:", -1) |
} |
+type compileError struct { |
+ Line int `json:"line"` |
+ Column int `json:"column"` |
+ Error string `json:"error"` |
+} |
+ |
// mainHandler handles the GET and POST of the main page. |
func mainHandler(w http.ResponseWriter, r *http.Request) { |
log.Printf("Main Handler: %q\n", r.URL.Path) |
@@ -867,10 +891,41 @@ func mainHandler(w http.ResponseWriter, r *http.Request) { |
} |
message, err := doCmd(cmd) |
+ |
+ outputLines := strings.Split(message, "\n") |
+ errorLines := []compileError{} |
+ errorRE := regexp.MustCompile(fmt.Sprintf("^.*%s.cpp:(\\d+):(\\d+):\\s*(.*)", hash)) |
jcgregorio
2014/10/15 19:59:50
Move to top of file so it's only compiled once.
humper
2014/10/15 21:03:59
Done.
|
+ for _, line := range outputLines { |
+ match := errorRE.FindStringSubmatch(line) |
+ if len(match) > 0 { |
+ lineNumber, parseError := strconv.Atoi(match[1]) |
+ if parseError != nil { |
+ log.Printf("ERROR: Couldn't parse line number from %s\n", match[1]) |
jcgregorio
2014/10/15 19:59:50
Add a TODO to switch from log to glog (http://godo
tfarina
2014/10/15 20:05:21
I will do that. I have a bug filed for that: https
|
+ continue |
+ } |
+ columnNumber, parseError := strconv.Atoi(match[2]) |
+ if parseError != nil { |
+ log.Printf("ERROR: Couldn't parse column number from %s\n", match[2]) |
+ continue |
+ } |
+ errorLines = append(errorLines, |
+ compileError{ |
+ Line: lineNumber, |
+ Column: columnNumber, |
+ Error: match[3], |
+ }) |
+ } |
+ } |
+ |
if err != nil { |
- reportTryError(w, r, err, "Failed to run the code:\n"+message, hash) |
+ if len(errorLines) > 0 { |
+ reportCompileError(w, r, errorLines, hash) |
+ } else { |
+ reportTryError(w, r, err, "Failed to run the code:\n"+message, hash) |
+ } |
return |
} |
+ |
png, err := ioutil.ReadFile("../../../inout/" + hash + ".png") |
if err != nil { |
reportTryError(w, r, err, "Failed to open the generated PNG.", hash) |