static GLboolean
Parse_ScalarSrcReg(struct parse_state *parseState, struct vp_src_register *srcReg)
{
   GLubyte token[100];

   srcReg->RelAddr = GL_FALSE;

   /* check for '-' */
   if (!Peek_Token(parseState, token))
      RETURN_ERROR;
   if (token[0] == '-') {
      srcReg->Negate = GL_TRUE;
      (void) Parse_String(parseState, "-"); /* consume '-' */
      if (!Peek_Token(parseState, token))
         RETURN_ERROR;
   }
   else {
      srcReg->Negate = GL_FALSE;
   }

   /* Src reg can be R<n>, c[n], c[n +/- offset], or a named vertex attrib */
   if (token[0] == 'R') {
      srcReg->File = PROGRAM_TEMPORARY;
      if (!Parse_TempReg(parseState, &srcReg->Index))
         RETURN_ERROR;
   }
   else if (token[0] == 'c') {
      if (!Parse_ParamReg(parseState, srcReg))
         RETURN_ERROR;
   }
   else if (token[0] == 'v') {
      srcReg->File = PROGRAM_INPUT;
      if (!Parse_AttribReg(parseState, &srcReg->Index))
         RETURN_ERROR;
   }
   else {
      RETURN_ERROR2("Bad source register name", token);
   }

   /* Look for .[xyzw] suffix */
   if (!Parse_String(parseState, "."))
      RETURN_ERROR;

   if (!Parse_Token(parseState, token))
      RETURN_ERROR;

   if (token[0] == 'x' && token[1] == 0) {
      srcReg->Swizzle[0] = 0;
   }
   else if (token[0] == 'y' && token[1] == 0) {
      srcReg->Swizzle[0] = 1;
   }
   else if (token[0] == 'z' && token[1] == 0) {
      srcReg->Swizzle[0] = 2;
   }
   else if (token[0] == 'w' && token[1] == 0) {
      srcReg->Swizzle[0] = 3;
   }
   else {
      RETURN_ERROR1("Bad scalar source suffix");
   }
   srcReg->Swizzle[1] = srcReg->Swizzle[2] = srcReg->Swizzle[3] = 0;

   return GL_TRUE;
}
/**
 * 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 vp_instruction *inst)
{
   const GLubyte *str;
   GLubyte *msg;
   GLuint len;
   GLubyte token[100];
   struct vp_src_register *srcReg = &inst->SrcReg[0];

   inst->Opcode = VP_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 = _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->Negate = GL_FALSE;
      srcReg->Swizzle[0] = 0;
      srcReg->Swizzle[1] = 1;
      srcReg->Swizzle[2] = 2;
      srcReg->Swizzle[3] = 3;

      /* 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, &srcReg->Index))
            RETURN_ERROR;
      }
      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, &srcReg->Index))
            RETURN_ERROR;
      }
      else if (token[0] == 'o') {
         srcReg->File = PROGRAM_OUTPUT;
         if (!Parse_OutputReg(parseState, &srcReg->Index))
            RETURN_ERROR;
      }
      else {
         RETURN_ERROR2("Bad source register name", token);
      }
   }
   else {
      srcReg->File = 0;
   }

   /* semicolon */
   if (!Parse_String(parseState, ";"))
      RETURN_ERROR;

   return GL_TRUE;
}
static GLboolean
Parse_SwizzleSrcReg(struct parse_state *parseState, struct vp_src_register *srcReg)
{
   GLubyte token[100];

   srcReg->RelAddr = GL_FALSE;

   /* check for '-' */
   if (!Peek_Token(parseState, token))
      RETURN_ERROR;
   if (token[0] == '-') {
      (void) Parse_String(parseState, "-");
      srcReg->Negate = GL_TRUE;
      if (!Peek_Token(parseState, token))
         RETURN_ERROR;
   }
   else {
      srcReg->Negate = GL_FALSE;
   }

   /* Src reg can be R<n>, c[n], c[n +/- offset], or a named vertex attrib */
   if (token[0] == 'R') {
      srcReg->File = PROGRAM_TEMPORARY;
      if (!Parse_TempReg(parseState, &srcReg->Index))
         RETURN_ERROR;
   }
   else if (token[0] == 'c') {
      if (!Parse_ParamReg(parseState, srcReg))
         RETURN_ERROR;
   }
   else if (token[0] == 'v') {
      srcReg->File = PROGRAM_INPUT;
      if (!Parse_AttribReg(parseState, &srcReg->Index))
         RETURN_ERROR;
   }
   else {
      RETURN_ERROR2("Bad source register name", token);
   }

   /* init swizzle fields */
   srcReg->Swizzle[0] = 0;
   srcReg->Swizzle[1] = 1;
   srcReg->Swizzle[2] = 2;
   srcReg->Swizzle[3] = 3;

   /* Look for optional swizzle suffix */
   if (!Peek_Token(parseState, token))
      RETURN_ERROR;
   if (token[0] == '.') {
      (void) Parse_String(parseState, ".");  /* consume . */

      if (!Parse_Token(parseState, token))
         RETURN_ERROR;

      if (token[1] == 0) {
         /* single letter swizzle */
         if (token[0] == 'x')
            ASSIGN_4V(srcReg->Swizzle, 0, 0, 0, 0);
         else if (token[0] == 'y')
            ASSIGN_4V(srcReg->Swizzle, 1, 1, 1, 1);
         else if (token[0] == 'z')
            ASSIGN_4V(srcReg->Swizzle, 2, 2, 2, 2);
         else if (token[0] == 'w')
            ASSIGN_4V(srcReg->Swizzle, 3, 3, 3, 3);
         else
            RETURN_ERROR1("Expected x, y, z, or w");
      }
      else {
         /* 2, 3 or 4-component swizzle */
         GLint k;
         for (k = 0; token[k] && k < 5; k++) {
            if (token[k] == 'x')
               srcReg->Swizzle[k] = 0;
            else if (token[k] == 'y')
               srcReg->Swizzle[k] = 1;
            else if (token[k] == 'z')
               srcReg->Swizzle[k] = 2;
            else if (token[k] == 'w')
               srcReg->Swizzle[k] = 3;
            else
               RETURN_ERROR;
         }
         if (k >= 5)
            RETURN_ERROR;
      }
   }

   return GL_TRUE;
}
static GLboolean
Parse_SwizzleSrcReg(struct parse_state *parseState, struct prog_src_register *srcReg)
{
   GLubyte token[100];
   GLint idx;

   srcReg->RelAddr = GL_FALSE;

   /* check for '-' */
   if (!Peek_Token(parseState, token))
      RETURN_ERROR;
   if (token[0] == '-') {
      (void) Parse_String(parseState, "-");
      srcReg->NegateBase = NEGATE_XYZW;
      if (!Peek_Token(parseState, token))
         RETURN_ERROR;
   }
   else {
      srcReg->NegateBase = NEGATE_NONE;
   }

   /* Src reg can be R<n>, c[n], c[n +/- offset], or a named vertex attrib */
   if (token[0] == 'R') {
      srcReg->File = PROGRAM_TEMPORARY;
      if (!Parse_TempReg(parseState, &idx))
         RETURN_ERROR;
      srcReg->Index = idx;
   }
   else if (token[0] == 'c') {
      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 {
      RETURN_ERROR2("Bad source register name", token);
   }

   /* init swizzle fields */
   srcReg->Swizzle = SWIZZLE_NOOP;

   /* Look for optional swizzle suffix */
   if (!Peek_Token(parseState, token))
      RETURN_ERROR;
   if (token[0] == '.') {
      (void) Parse_String(parseState, ".");  /* consume . */

      if (!Parse_Token(parseState, token))
         RETURN_ERROR;

      if (token[1] == 0) {
         /* single letter swizzle */
         if (token[0] == 'x')
            srcReg->Swizzle = SWIZZLE_XXXX;
         else if (token[0] == 'y')
            srcReg->Swizzle = SWIZZLE_YYYY;
         else if (token[0] == 'z')
            srcReg->Swizzle = SWIZZLE_ZZZZ;
         else if (token[0] == 'w')
            srcReg->Swizzle = SWIZZLE_WWWW;
         else
            RETURN_ERROR1("Expected x, y, z, or w");
      }
      else {
         /* 2, 3 or 4-component swizzle */
         GLint k;

         srcReg->Swizzle = 0;

         for (k = 0; token[k] && k < 5; k++) {
            if (token[k] == 'x')
               srcReg->Swizzle |= 0 << (k*3);
            else if (token[k] == 'y')
               srcReg->Swizzle |= 1 << (k*3);
            else if (token[k] == 'z')
               srcReg->Swizzle |= 2 << (k*3);
            else if (token[k] == 'w')
               srcReg->Swizzle |= 3 << (k*3);
            else
               RETURN_ERROR;
         }
         if (k >= 5)
            RETURN_ERROR;
      }
   }

   return GL_TRUE;
}