+/**
+ * The PRINT instruction is Mesa-specific and is meant as a debugging aid for
+ * the vertex program developer.
+ * The NV_vertex_program extension grammar is modified as follows:
+ *
+ * <instruction> ::= <ARL-instruction>
+ * | ...
+ * | <PRINT-instruction>
+ *
+ * <PRINT-instruction> ::= "PRINT" <string literal>
+ * | "PRINT" <string literal> "," <srcReg>
+ * | "PRINT" <string literal> "," <dstReg>
+ */
+static GLboolean
+Parse_PrintInstruction(struct parse_state *parseState, struct prog_instruction *inst)
+{
+ const GLubyte *str;
+ GLubyte *msg;
+ GLuint len;
+ GLubyte token[100];
+ struct prog_src_register *srcReg = &inst->SrcReg[0];
+ GLint idx;
+
+ inst->Opcode = OPCODE_PRINT;
+ inst->StringPos = parseState->curLine - parseState->start;
+
+ /* The first argument is a literal string 'just like this' */
+ if (!Parse_String(parseState, "'"))
+ RETURN_ERROR;
+
+ str = parseState->pos;
+ for (len = 0; str[len] != '\''; len++) /* find closing quote */
+ ;
+ parseState->pos += len + 1;
+ msg = (GLubyte*) _mesa_malloc(len + 1);
+
+ _mesa_memcpy(msg, str, len);
+ msg[len] = 0;
+ inst->Data = msg;
+
+ /* comma */
+ if (Parse_String(parseState, ",")) {
+
+ /* The second argument is a register name */
+ if (!Peek_Token(parseState, token))
+ RETURN_ERROR;
+
+ srcReg->RelAddr = GL_FALSE;
+ srcReg->NegateBase = NEGATE_NONE;
+ srcReg->Swizzle = SWIZZLE_NOOP;
+
+ /* Register can be R<n>, c[n], c[n +/- offset], a named vertex attrib,
+ * or an o[n] output register.
+ */
+ if (token[0] == 'R') {
+ srcReg->File = PROGRAM_TEMPORARY;
+ if (!Parse_TempReg(parseState, &idx))
+ RETURN_ERROR;
+ srcReg->Index = idx;
+ }
+ else if (token[0] == 'c') {
+ srcReg->File = PROGRAM_ENV_PARAM;
+ if (!Parse_ParamReg(parseState, srcReg))
+ RETURN_ERROR;
+ }
+ else if (token[0] == 'v') {
+ srcReg->File = PROGRAM_INPUT;
+ if (!Parse_AttribReg(parseState, &idx))
+ RETURN_ERROR;
+ srcReg->Index = idx;
+ }
+ else if (token[0] == 'o') {
+ srcReg->File = PROGRAM_OUTPUT;
+ if (!Parse_OutputReg(parseState, &idx))
+ RETURN_ERROR;
+ srcReg->Index = idx;
+ }
+ else {
+ RETURN_ERROR2("Bad source register name", token);
+ }
+ }
+ else {
+ srcReg->File = 0;
+ }
+
+ /* semicolon */
+ if (!Parse_String(parseState, ";"))
+ RETURN_ERROR;
+
+ return GL_TRUE;
+}
+
+