linker: Write errors to info log instead of stdout
diff --git a/linker.cpp b/linker.cpp
index 500a329..4d1ff01 100644
--- a/linker.cpp
+++ b/linker.cpp
@@ -65,6 +65,11 @@
  */
 #include <cstdlib>
 #include <cstdio>
+#include <cstdarg>
+
+extern "C" {
+#include <talloc.h>
+}
 
 #include "main/mtypes.h"
 #include "glsl_symbol_table.h"
@@ -109,6 +114,18 @@
 
 
 void
+linker_error_printf(glsl_program *prog, const char *fmt, ...)
+{
+   va_list ap;
+
+   prog->InfoLog = talloc_strdup_append(prog->InfoLog, "error: ");
+   va_start(ap, fmt);
+   prog->InfoLog = talloc_vasprintf_append(prog->InfoLog, fmt, ap);
+   va_end(ap);
+}
+
+
+void
 invalidate_variable_locations(glsl_shader *sh, enum ir_variable_mode mode,
 			      int generic_base)
 {
@@ -167,20 +184,22 @@
  * \param shader  Vertex shader executable to be verified
  */
 bool
-validate_vertex_shader_executable(struct glsl_shader *shader)
+validate_vertex_shader_executable(struct glsl_program *prog,
+				  struct glsl_shader *shader)
 {
    if (shader == NULL)
       return true;
 
    if (!shader->symbols->get_function("main")) {
-      printf("error: vertex shader lacks `main'\n");
+      linker_error_printf(prog, "vertex shader lacks `main'\n");
       return false;
    }
 
    find_assignment_visitor find("gl_Position");
    find.run(&shader->ir);
    if (!find.variable_found()) {
-      printf("error: vertex shader does not write to `gl_Position'\n");
+      linker_error_printf(prog,
+			  "vertex shader does not write to `gl_Position'\n");
       return false;
    }
 
@@ -194,13 +213,14 @@
  * \param shader  Fragment shader executable to be verified
  */
 bool
-validate_fragment_shader_executable(struct glsl_shader *shader)
+validate_fragment_shader_executable(struct glsl_program *prog,
+				    struct glsl_shader *shader)
 {
    if (shader == NULL)
       return true;
 
    if (!shader->symbols->get_function("main")) {
-      printf("error: fragment shader lacks `main'\n");
+      linker_error_printf(prog, "fragment shader lacks `main'\n");
       return false;
    }
 
@@ -211,14 +231,14 @@
    frag_data.run(&shader->ir);
 
    if (!frag_color.variable_found() && !frag_data.variable_found()) {
-      printf("error: fragment shader does not write to `gl_FragColor' or "
-	     "`gl_FragData'\n");
+      linker_error_printf(prog, "fragment shader does not write to "
+			  "`gl_FragColor' or `gl_FragData'\n");
       return false;
    }
 
    if (frag_color.variable_found() && frag_data.variable_found()) {
-      printf("error: fragment shader write to both `gl_FragColor' and "
-	     "`gl_FragData'\n");
+      linker_error_printf(prog,  "fragment shader writes to both "
+			  "`gl_FragColor' and `gl_FragData'\n");
       return false;
    }
 
@@ -230,7 +250,8 @@
  * Perform validation of uniforms used across multiple shader stages
  */
 bool
-cross_validate_uniforms(struct glsl_shader **shaders, unsigned num_shaders)
+cross_validate_uniforms(struct glsl_program *prog,
+			struct glsl_shader **shaders, unsigned num_shaders)
 {
    /* Examine all of the uniforms in all of the shaders and cross validate
     * them.
@@ -250,18 +271,19 @@
 	 ir_variable *const existing = uniforms.get_variable(var->name);
 	 if (existing != NULL) {
 	    if (var->type != existing->type) {
-	       printf("error: uniform `%s' declared as type `%s' and "
-		      "type `%s'\n",
-		      var->name, var->type->name, existing->type->name);
+	       linker_error_printf(prog, "uniform `%s' declared as type "
+				   "`%s' and type `%s'\n",
+				   var->name, var->type->name,
+				   existing->type->name);
 	       return false;
 	    }
 
 	    if (var->constant_value != NULL) {
 	       if (existing->constant_value != NULL) {
 		  if (!var->constant_value->has_value(existing->constant_value)) {
-		     printf("error: initializers for uniform `%s' have "
-			    "differing values\n",
-			    var->name);
+		     linker_error_printf(prog, "initializers for uniform "
+					 "`%s' have differing values\n",
+					 var->name);
 		     return false;
 		  }
 	       } else
@@ -284,7 +306,8 @@
  * Validate that outputs from one stage match inputs of another
  */
 bool
-cross_validate_outputs_to_inputs(glsl_shader *producer, glsl_shader *consumer)
+cross_validate_outputs_to_inputs(struct glsl_program *prog,
+				 glsl_shader *producer, glsl_shader *consumer)
 {
    glsl_symbol_table parameters;
    /* FINISHME: Figure these out dynamically. */
@@ -324,47 +347,53 @@
 	 /* Check that the types match between stages.
 	  */
 	 if (input->type != output->type) {
-	    printf("error: %s shader output `%s' delcared as type `%s', but "
-		   "%s shader input declared as type `%s'\n",
-		   producer_stage, output->name, output->type->name,
-		   consumer_stage, input->type->name);
+	    linker_error_printf(prog,
+				"%s shader output `%s' delcared as "
+				"type `%s', but %s shader input declared "
+				"as type `%s'\n",
+				producer_stage, output->name,
+				output->type->name,
+				consumer_stage, input->type->name);
 	    return false;
 	 }
 
 	 /* Check that all of the qualifiers match between stages.
 	  */
 	 if (input->centroid != output->centroid) {
-	    printf("error: %s shader output `%s' %s centroid qualifier, but "
-		   "%s shader input %s centroid qualifier\n",
-		   producer_stage,
-		   output->name,
-		   (output->centroid) ? "has" : "lacks",
-		   consumer_stage,
-		   (input->centroid) ? "has" : "lacks");
+	    linker_error_printf(prog,
+				"%s shader output `%s' %s centroid qualifier, "
+				"but %s shader input %s centroid qualifier\n",
+				producer_stage,
+				output->name,
+				(output->centroid) ? "has" : "lacks",
+				consumer_stage,
+				(input->centroid) ? "has" : "lacks");
 	    return false;
 	 }
 
 	 if (input->invariant != output->invariant) {
-	    printf("error: %s shader output `%s' %s invariant qualifier, but "
-		   "%s shader input %s invariant qualifier\n",
-		   producer_stage,
-		   output->name,
-		   (output->invariant) ? "has" : "lacks",
-		   consumer_stage,
-		   (input->invariant) ? "has" : "lacks");
+	    linker_error_printf(prog,
+				"%s shader output `%s' %s invariant qualifier, "
+				"but %s shader input %s invariant qualifier\n",
+				producer_stage,
+				output->name,
+				(output->invariant) ? "has" : "lacks",
+				consumer_stage,
+				(input->invariant) ? "has" : "lacks");
 	    return false;
 	 }
 
 	 if (input->interpolation != output->interpolation) {
-	    printf("error: %s shader output `%s' specifies %s interpolation "
-		   "qualifier, "
-		   "but %s shader input specifies %s interpolation "
-		   "qualifier\n",
-		   producer_stage,
-		   output->name,
-		   output->interpolation_string(),
-		   consumer_stage,
-		   input->interpolation_string());
+	    linker_error_printf(prog,
+				"%s shader output `%s' specifies %s "
+				"interpolation qualifier, "
+				"but %s shader input specifies %s "
+				"interpolation qualifier\n",
+				producer_stage,
+				output->name,
+				output->interpolation_string(),
+				consumer_stage,
+				input->interpolation_string());
 	    return false;
 	 }
       }
@@ -741,6 +770,11 @@
    prog->Validated = false;
    prog->_Used = false;
 
+   if (prog->InfoLog != NULL)
+      talloc_free(prog->InfoLog);
+
+   prog->InfoLog = talloc_strdup(NULL, "");
+
    /* Separate the shaders into groups based on their type.
     */
    struct glsl_shader **vert_shader_list;
@@ -775,8 +809,8 @@
 
    /* Verify that each of the per-target executables is valid.
     */
-   if (!validate_vertex_shader_executable(vert_shader_list[0])
-       || !validate_fragment_shader_executable(frag_shader_list[0]))
+   if (!validate_vertex_shader_executable(prog, vert_shader_list[0])
+       || !validate_fragment_shader_executable(prog, frag_shader_list[0]))
       goto done;
 
 
@@ -795,12 +829,14 @@
       prog->_NumLinkedShaders++;
    }
 
-   if (cross_validate_uniforms(prog->_LinkedShaders, prog->_NumLinkedShaders)) {
+   if (cross_validate_uniforms(prog, prog->_LinkedShaders,
+			       prog->_NumLinkedShaders)) {
       /* Validate the inputs of each stage with the output of the preceeding
        * stage.
        */
       for (unsigned i = 1; i < prog->_NumLinkedShaders; i++) {
-	 if (!cross_validate_outputs_to_inputs(prog->_LinkedShaders[i - 1],
+	 if (!cross_validate_outputs_to_inputs(prog,
+					       prog->_LinkedShaders[i - 1],
 					       prog->_LinkedShaders[i]))
 	    goto done;
       }