示例#1
0
bool MA_ParseTVert( idParser &parser, maAttribHeader_t *header )
{

	maMesh_t *pMesh = &maGlobal.currentObject->mesh;
	idToken token;
	
	//This is not the texture coordinates. It is just the name so ignore it
	if( strstr( header->name, "uvsn" ) )
	{
		return true;
	}
	
	//Allocate enough space for all the data
	if( !pMesh->tvertexes )
	{
		pMesh->numTVertexes = header->size;
		pMesh->tvertexes = ( idVec2 * ) Mem_Alloc( sizeof( idVec2 ) * pMesh->numTVertexes );
	}
	
	//Get the start and end index for this attribute
	int minIndex, maxIndex;
	
	if( !MA_ParseHeaderIndex( header, minIndex, maxIndex, "TextureCoordHeader", "uvsp" ) )
	{
		//This was just a header
		return true;
	}
	
	parser.ReadToken( &token );
	
	if( !token.Icmp( "-" ) )
	{
		idToken tk2;
		parser.ReadToken( &tk2 );
		
		if( !tk2.Icmp( "type" ) )
		{
			parser.SkipUntilString( "float2" );
		}
		else
		{
			parser.UnreadToken( &tk2 );
			parser.UnreadToken( &token );
		}
	}
	else
	{
		parser.UnreadToken( &token );
	}
	
	//Read each tvert
	for( int i = minIndex; i <= maxIndex; i++ )
	{
		pMesh->tvertexes[i].x = parser.ParseFloat();
		pMesh->tvertexes[i].y = 1.0f - parser.ParseFloat();
	}
	
	return true;
}
示例#2
0
bool MA_ParseNormal(idParser& parser, maAttribHeader_t* header) {

    maMesh_t* pMesh = &maGlobal.currentObject->mesh;
    idToken token;

    //Allocate enough space for all the verts if this is the first attribute for verticies
    if(!pMesh->normals) {
        pMesh->numNormals = header->size;
        pMesh->normals = (idVec3 *)Mem_Alloc( sizeof( idVec3 ) * pMesh->numNormals );
    }

    //Get the start and end index for this attribute
    int minIndex, maxIndex;
    if(!MA_ParseHeaderIndex(header, minIndex, maxIndex, "NormalHeader", NULL)) {
        //This was just a header
        return true;
    }


    parser.ReadToken(&token);
    if(!token.Icmp("-")) {
        idToken tk2;
        parser.ReadToken(&tk2);
        if(!tk2.Icmp("type")) {
            parser.SkipUntilString("float3");
        } else {
            parser.UnreadToken(&tk2);
            parser.UnreadToken(&token);
        }
    } else {
        parser.UnreadToken(&token);
    }


    //Read each vert
    for(int i = minIndex; i <= maxIndex; i++) {
        pMesh->normals[i].x = parser.ParseFloat();

        //Adjust the normals for the change in coordinate systems
        pMesh->normals[i].z = parser.ParseFloat();
        pMesh->normals[i].y = -parser.ParseFloat();

        pMesh->normals[i].Normalize();

    }

    pMesh->normalsParsed = true;
    pMesh->nextNormal = 0;

    return true;
}
示例#3
0
bool MA_ParseVertexTransforms(idParser& parser, maAttribHeader_t* header) {

    maMesh_t* pMesh = &maGlobal.currentObject->mesh;
    idToken token;

    //Allocate enough space for all the verts if this is the first attribute for verticies
    if(!pMesh->vertTransforms) {
        if(header->size == 0) {
            header->size = 1;
        }

        pMesh->numVertTransforms = header->size;
        pMesh->vertTransforms = (idVec4 *)Mem_Alloc( sizeof( idVec4 ) * pMesh->numVertTransforms );
        pMesh->nextVertTransformIndex = 0;
    }

    //Get the start and end index for this attribute
    int minIndex, maxIndex;
    if(!MA_ParseHeaderIndex(header, minIndex, maxIndex, "VertexTransformHeader", NULL)) {
        //This was just a header
        return true;
    }

    parser.ReadToken(&token);
    if(!token.Icmp("-")) {
        idToken tk2;
        parser.ReadToken(&tk2);
        if(!tk2.Icmp("type")) {
            parser.SkipUntilString("float3");
        } else {
            parser.UnreadToken(&tk2);
            parser.UnreadToken(&token);
        }
    } else {
        parser.UnreadToken(&token);
    }

    //Read each vert
    for(int i = minIndex; i <= maxIndex; i++) {
        pMesh->vertTransforms[pMesh->nextVertTransformIndex].x = parser.ParseFloat();
        pMesh->vertTransforms[pMesh->nextVertTransformIndex].z = parser.ParseFloat();
        pMesh->vertTransforms[pMesh->nextVertTransformIndex].y = -parser.ParseFloat();

        //w hold the vert index
        pMesh->vertTransforms[pMesh->nextVertTransformIndex].w = i;

        pMesh->nextVertTransformIndex++;
    }

    return true;
}
示例#4
0
/*
================
idTypeInfoGen::ParseConstantValue
================
*/
void idTypeInfoGen::ParseConstantValue( const char *scope, idParser &src, idStr &value ) {
	idToken token;
	idStr constantString;

	int indent = 0;
	while( src.ReadToken( &token ) ) {
		if ( token == "(" ) {
			indent++;
		} else if ( token == ")" ) {
			indent--;
		} else if ( indent == 0 && ( token == ";" || token == "," || token == "}" ) ) {
			src.UnreadToken( &token );
			break;
		} else if ( token.type == TT_NAME ) {
			constantString = token;
			while( src.CheckTokenString( "::" ) ) {
				src.ExpectTokenType( TT_NAME, 0, &token );
				constantString += "::" + token;
			}
			value += va( "%d", GetIntegerConstant( scope, constantString, src ) );
			continue;
		}
		value += token;
	}
}
示例#5
0
bool MA_ParseTransform(idParser& parser) {

    maNodeHeader_t	header;
    maTransform_t*	transform;
    memset(&header, 0, sizeof(header));

    //Allocate room for the transform
    transform = (maTransform_t *)Mem_Alloc( sizeof( maTransform_t ) );
    memset(transform, 0, sizeof(maTransform_t));
    transform->scale.x = transform->scale.y = transform->scale.z = 1;

    //Get the header info from the transform
    MA_ParseNodeHeader(parser, &header);

    //Read the transform attributes
    idToken token;
    while(parser.ReadToken(&token)) {
        if(IsNodeComplete(token)) {
            parser.UnreadToken(&token);
            break;
        }
        if(!token.Icmp("setAttr")) {
            parser.ReadToken(&token);
            if(!token.Icmp(".t")) {
                if(!MA_ReadVec3(parser, transform->translate)) {
                    return false;
                }
                transform->translate.y *=  -1;
            } else if (!token.Icmp(".r")) {
                if(!MA_ReadVec3(parser, transform->rotate)) {
                    return false;
                }
            } else if (!token.Icmp(".s")) {
                if(!MA_ReadVec3(parser, transform->scale)) {
                    return false;
                }
            } else {
                parser.SkipRestOfLine();
            }
        }
    }

    if(header.parent[0] != 0) {
        //Find the parent
        maTransform_t**	parent;
        maGlobal.model->transforms.Get(header.parent, &parent);
        if(parent) {
            transform->parent = *parent;
        }
    }

    //Add this transform to the list
    maGlobal.model->transforms.Set(header.name, transform);
    return true;
}
示例#6
0
void MA_ParseFileNode( idParser &parser )
{

	//Get the header info from the node
	maNodeHeader_t	header;
	MA_ParseNodeHeader( parser, &header );
	
	//Read the transform attributes
	idToken token;
	
	while( parser.ReadToken( &token ) )
	{
		if( IsNodeComplete( token ) )
		{
			parser.UnreadToken( &token );
			break;
		}
		
		if( !token.Icmp( "setAttr" ) )
		{
			maAttribHeader_t attribHeader;
			MA_ParseAttribHeader( parser, &attribHeader );
			
			if( strstr( attribHeader.name, ".ftn" ) )
			{
				parser.SkipUntilString( "string" );
				parser.ReadToken( &token );
				
				if( !token.Icmp( "(" ) )
				{
					parser.ReadToken( &token );
				}
				
				maFileNode_t *fileNode;
				fileNode = ( maFileNode_t * ) Mem_Alloc( sizeof( maFileNode_t ) );
				strcpy( fileNode->name, header.name );
				strcpy( fileNode->path, token.c_str() );
				
				maGlobal.model->fileNodes.Set( fileNode->name, fileNode );
			}
			else
			{
				parser.SkipRestOfLine();
			}
		}
	}
}
示例#7
0
void MA_ParseMesh(idParser& parser) {

    maObject_t	*object;
    object = (maObject_t *)Mem_Alloc( sizeof( maObject_t ) );
    memset( object, 0, sizeof( maObject_t ) );
    maGlobal.model->objects.Append( object );
    maGlobal.currentObject = object;
    object->materialRef = -1;


    //Get the header info from the mesh
    maNodeHeader_t	header;
    MA_ParseNodeHeader(parser, &header);

    //Find my parent
    if(header.parent[0] != 0) {
        //Find the parent
        maTransform_t**	parent;
        maGlobal.model->transforms.Get(header.parent, &parent);
        if(parent) {
            maGlobal.currentObject->mesh.transform = *parent;
        }
    }

    strcpy(object->name, header.name);

    //Read the transform attributes
    idToken token;
    while(parser.ReadToken(&token)) {
        if(IsNodeComplete(token)) {
            parser.UnreadToken(&token);
            break;
        }
        if(!token.Icmp("setAttr")) {
            maAttribHeader_t header;
            MA_ParseAttribHeader(parser, &header);

            if(strstr(header.name, ".vt")) {
                MA_ParseVertex(parser, &header);
            } else if (strstr(header.name, ".ed")) {
                MA_ParseEdge(parser, &header);
            } else if (strstr(header.name, ".pt")) {
                MA_ParseVertexTransforms(parser, &header);
            } else if (strstr(header.name, ".n")) {
                MA_ParseNormal(parser, &header);
            } else if (strstr(header.name, ".fc")) {
                MA_ParseFace(parser, &header);
            } else if (strstr(header.name, ".clr")) {
                MA_ParseColor(parser, &header);
            } else if (strstr(header.name, ".uvst")) {
                MA_ParseTVert(parser, &header);
            } else {
                parser.SkipRestOfLine();
            }
        }
    }


    maMesh_t* pMesh = &maGlobal.currentObject->mesh;

    //Get the verts from the edge
    for(int i = 0; i < pMesh->numFaces; i++) {
        for(int j = 0; j < 3; j++) {
            int edge = pMesh->faces[i].edge[j];
            if(edge < 0) {
                edge = idMath::Fabs(edge)-1;
                pMesh->faces[i].vertexNum[j] = pMesh->edges[edge].y;
            } else {
                pMesh->faces[i].vertexNum[j] = pMesh->edges[edge].x;
            }
        }
    }

    //Get the normals
    if(pMesh->normalsParsed) {
        for(int i = 0; i < pMesh->numFaces; i++) {
            for(int j = 0; j < 3; j++) {

                //Is this vertex shared
                int sharedFace = -1;
                int sharedVert = -1;

                if(MA_QuickIsVertShared(i, j)) {
                    MA_GetSharedFace(i, j, sharedFace, sharedVert);
                }

                if(sharedFace != -1) {
                    //Get the normal from the share
                    pMesh->faces[i].vertexNormals[j] = pMesh->faces[sharedFace].vertexNormals[sharedVert];

                } else {
                    //The vertex is not shared so get the next normal
                    if(pMesh->nextNormal >= pMesh->numNormals) {
                        //We are using more normals than exist
                        throw idException(va("Maya Loader '%s': Invalid Normals Index.", parser.GetFileName()));
                    }
                    pMesh->faces[i].vertexNormals[j] = pMesh->normals[pMesh->nextNormal];
                    pMesh->nextNormal++;
                }
            }
        }
    }

    //Now that the normals are good...lets reorder the verts to make the tris face the right way
    for(int i = 0; i < pMesh->numFaces; i++) {
        int tmp = pMesh->faces[i].vertexNum[1];
        pMesh->faces[i].vertexNum[1] = pMesh->faces[i].vertexNum[2];
        pMesh->faces[i].vertexNum[2] = tmp;

        idVec3 tmpVec = pMesh->faces[i].vertexNormals[1];
        pMesh->faces[i].vertexNormals[1] = pMesh->faces[i].vertexNormals[2];
        pMesh->faces[i].vertexNormals[2] = tmpVec;

        tmp = pMesh->faces[i].tVertexNum[1];
        pMesh->faces[i].tVertexNum[1] = pMesh->faces[i].tVertexNum[2];
        pMesh->faces[i].tVertexNum[2] = tmp;

        tmp = pMesh->faces[i].vertexColors[1];
        pMesh->faces[i].vertexColors[1] = pMesh->faces[i].vertexColors[2];
        pMesh->faces[i].vertexColors[2] = tmp;
    }

    //Now apply the pt transformations
    for(int i = 0; i < pMesh->numVertTransforms; i++) {
        pMesh->vertexes[(int)pMesh->vertTransforms[i].w] +=  pMesh->vertTransforms[i].ToVec3();
    }

    MA_VERBOSE((va("MESH %s - parent %s\n", header.name, header.parent)));
    MA_VERBOSE((va("\tverts:%d\n",maGlobal.currentObject->mesh.numVertexes)));
    MA_VERBOSE((va("\tfaces:%d\n",maGlobal.currentObject->mesh.numFaces)));
}
示例#8
0
bool MA_ParseFace(idParser& parser, maAttribHeader_t* header) {

    maMesh_t* pMesh = &maGlobal.currentObject->mesh;
    idToken token;

    //Allocate enough space for all the verts if this is the first attribute for verticies
    if(!pMesh->faces) {
        pMesh->numFaces = header->size;
        pMesh->faces = (maFace_t *)Mem_Alloc( sizeof( maFace_t ) * pMesh->numFaces );
    }

    //Get the start and end index for this attribute
    int minIndex, maxIndex;
    if(!MA_ParseHeaderIndex(header, minIndex, maxIndex, "FaceHeader", NULL)) {
        //This was just a header
        return true;
    }

    //Read the face data
    int currentFace = minIndex-1;
    while(parser.ReadToken(&token)) {
        if(IsNodeComplete(token)) {
            parser.UnreadToken(&token);
            break;
        }

        if(!token.Icmp("f")) {
            int count = parser.ParseInt();
            if(count != 3) {
                throw idException(va("Maya Loader '%s': Face is not a triangle.", parser.GetFileName()));
            }
            //Increment the face number because a new face always starts with an "f" token
            currentFace++;

            //We cannot reorder edges until later because the normal processing
            //assumes the edges are in the original order
            pMesh->faces[currentFace].edge[0] = parser.ParseInt();
            pMesh->faces[currentFace].edge[1] = parser.ParseInt();
            pMesh->faces[currentFace].edge[2] = parser.ParseInt();

            //Some more init stuff
            pMesh->faces[currentFace].vertexColors[0] = pMesh->faces[currentFace].vertexColors[1] = pMesh->faces[currentFace].vertexColors[2] = -1;

        } else if(!token.Icmp("mu")) {
            /* int uvstIndex = */ parser.ParseInt();
            int count = parser.ParseInt();
            if(count != 3) {
                throw idException(va("Maya Loader '%s': Invalid texture coordinates.", parser.GetFileName()));
            }
            pMesh->faces[currentFace].tVertexNum[0] = parser.ParseInt();
            pMesh->faces[currentFace].tVertexNum[1] = parser.ParseInt();
            pMesh->faces[currentFace].tVertexNum[2] = parser.ParseInt();

        } else if(!token.Icmp("mf")) {
            int count = parser.ParseInt();
            if(count != 3) {
                throw idException(va("Maya Loader '%s': Invalid texture coordinates.", parser.GetFileName()));
            }
            pMesh->faces[currentFace].tVertexNum[0] = parser.ParseInt();
            pMesh->faces[currentFace].tVertexNum[1] = parser.ParseInt();
            pMesh->faces[currentFace].tVertexNum[2] = parser.ParseInt();

        } else if(!token.Icmp("fc")) {

            int count = parser.ParseInt();
            if(count != 3) {
                throw idException(va("Maya Loader '%s': Invalid vertex color.", parser.GetFileName()));
            }
            pMesh->faces[currentFace].vertexColors[0] = parser.ParseInt();
            pMesh->faces[currentFace].vertexColors[1] = parser.ParseInt();
            pMesh->faces[currentFace].vertexColors[2] = parser.ParseInt();

        }
    }

    return true;
}
示例#9
0
/*
================
idTypeInfoGen::ParseScope
================
*/
void idTypeInfoGen::ParseScope( const char *scope, bool isTemplate, idParser &src, idClassTypeInfo *typeInfo ) {
	int indent;
	idToken token;
	idClassTypeInfo *classInfo;
	idEnumTypeInfo *enumInfo;
	idStr varType;
	bool isConst = false;
	bool isStatic = false;

	indent = 1;
	while( indent ) {
		if ( !src.ReadToken( &token ) ) {
			break;
		}

		if ( token == "{" ) {

			do {
				if ( token == "{" ) {
					indent++;
				} else if ( token == "}" ) {
					indent--;
				}
				varType += token + " ";
			} while( indent > 1 && src.ReadToken( &token ) );

		} else if ( token == "}" ) {

			assert( indent == 1 );
			indent--;

		} else if ( token == "<" ) {

			do {
				if ( token == "<" ) {
					indent++;
				} else if ( token == ">" ) {
					indent--;
				}
				varType += token + " ";
			} while( indent > 1 && src.ReadToken( &token ) );

		} else if ( token == ";" ) {

			varType = "";
			isConst = false;
			isStatic = false;

		} else if ( token == "public" || token == "protected" || token == "private" ) {

			if ( !src.ExpectTokenString( ":" ) ) {
				break;
			}
			varType = "";
			isConst = false;
			isStatic = false;

		} else if ( token == "friend" ) {

			// skip friend classes/methods
			while( src.ReadToken( &token ) ) {
				if ( token == "{" ) {
					indent++;
				} else if ( token == "}" ) {
					indent--;
					if ( indent == 1 ) {
						break;
					}
				} else if ( token == ";" && indent == 1 ) {
					break;
				}
			}

			varType = "";
			isConst = false;
			isStatic = false;

		} else if ( token == "template" ) {

			varType = "";

			if ( src.CheckTokenString( "<" ) ) {

				int indent = 1;
				varType += "< ";
				while( src.ReadToken( &token ) ) {
					if ( token == "<" ) {
						indent++;
					} else if ( token == ">" ) {
						indent--;
						if ( indent == 0 ) {
							break;
						}
					}
					varType += token + " ";
				}
				varType += ">";
			}

			if ( src.CheckTokenString( "class" ) ) {

				// parse template class
				classInfo = ParseClassType( scope, varType, true, false, src );
				if ( classInfo ) {
					classes.Append( classInfo );
				}

			} else {

				// skip template methods
				while( src.ReadToken( &token ) ) {
					if ( token == "{" ) {
						indent++;
					} else if ( token == "}" ) {
						indent--;
						if ( indent == 1 ) {
							break;
						}
					} else if ( token == ";" && indent == 1 ) {
						break;
					}
				}
			}

			varType = "";
			isConst = false;
			isStatic = false;

		} else if ( token == "namespace" ) {

			// parse namespace
			classInfo = ParseClassType( scope, "", isTemplate, false, src );
			delete classInfo;

		} else if ( token == "class" ) {

			// parse class
			classInfo = ParseClassType( scope, "", isTemplate, false, src );
			if ( classInfo ) {
				classes.Append( classInfo );
			}

		} else if ( token == "struct" ) {

			// parse struct
			classInfo = ParseClassType( scope, "", isTemplate, false, src );
			if ( classInfo ) {
				classes.Append( classInfo );
				varType = classInfo->scope + classInfo->typeName;
			}

		} else if ( token == "union" ) {

			// parse union
			classInfo = ParseClassType( scope, "", isTemplate, false, src );
			if ( classInfo ) {
				classes.Append( classInfo );
			}

		} else if ( token == "enum" ) {

			// parse enum
			enumInfo = ParseEnumType( scope, isTemplate, false, src );
			if ( enumInfo ) {
				enums.Append( enumInfo );
				varType = enumInfo->scope + enumInfo->typeName;
			}

		} else if ( token == "typedef" ) {

			if ( token == "class" ) {

				// parse typedef class
				classInfo = ParseClassType( scope, "", isTemplate, true, src );
				if ( classInfo ) {
					classes.Append( classInfo );
				}

			} else if ( src.CheckTokenString( "struct" ) ) {

				// parse typedef struct
				classInfo = ParseClassType( scope, "", isTemplate, true, src );
				if ( classInfo ) {
					classes.Append( classInfo );
				}

			} else if ( src.CheckTokenString( "union" ) ) {

				// parse typedef union
				classInfo = ParseClassType( scope, "", isTemplate, true, src );
				if ( classInfo ) {
					classes.Append( classInfo );
				}

			} else if ( src.CheckTokenString( "enum" ) ) {

				// parse typedef enum
				enumInfo = ParseEnumType( scope, isTemplate, true, src );
				if ( enumInfo ) {
					enums.Append( enumInfo );
				}

			} else {

				// skip other typedefs
				while( src.ReadToken( &token ) ) {
					if ( token == "{" ) {
						indent++;
					} else if ( token == "}" ) {
						indent--;
					} else if ( token == ";" && indent == 1 ) {
						break;
					}
				}
			}

			varType = "";
			isConst = false;
			isStatic = false;

		} else if ( token == "const" ) {

			varType += token + " ";
			isConst = true;

		} else if ( token == "static" ) {

			varType += token + " ";
			isStatic = true;

		} else if ( token.type == TT_NAME ) {
	
			assert( indent == 1 );

			// if this is a class operator
			if ( token == "operator" ) {
				while( src.ReadToken( &token ) ) {
					if ( token == "(" ) {
						src.UnreadToken( &token );
						break;
					}
				}
			}

			// if this is a class method
			if ( src.CheckTokenString( "(" ) ) {

				indent++;
				while( indent > 1 && src.ReadToken( &token ) ) {
					if ( token == "(" ) {
						indent++;
					} else if ( token == ")" ) {
						indent--;
					}
				}

				if ( src.CheckTokenString( "(" ) ) {
					indent++;
					while( indent > 1 && src.ReadToken( &token ) ) {
						if ( token == "(" ) {
							indent++;
						} else if ( token == ")" ) {
							indent--;
						}
					}
				}

				if ( src.CheckTokenString( "const" ) ) {
				}

				if ( src.CheckTokenString( "=" ) ) {

					src.ExpectTokenString( "0" );

				} else if ( src.CheckTokenString( "{" ) ) {
					indent++;
					while( indent > 1 && src.ReadToken( &token ) ) {
						if ( token == "{" ) {
							indent++;
						} else if ( token == "}" ) {
							indent--;
						}
					}
				}

				varType = "";
				isConst = false;
				isStatic = false;

			} else if ( ( isStatic || isConst ) && src.CheckTokenString( "=" ) ) {

				// constant
				idConstantInfo *constantInfo = new idConstantInfo;
				constantInfo->name = scope + token;
				constantInfo->type = varType;
				constantInfo->type.StripTrailing( ' ' );
				ParseConstantValue( scope, src, constantInfo->value );
				constants.Append( constantInfo );

			} else if ( isStatic ) {

				// static class variable
				varType += token + " ";

			} else {

				// check for class variables
				while( 1 ) {

					int arraySize = ParseArraySize( scope, src );

					if ( arraySize ) {
						idClassVariableInfo var;

						var.name = token;
						var.type = varType;
						var.type.StripTrailing( ' ' );
						var.type += va( "[%d]", arraySize );
						var.bits = 0;
						typeInfo->variables.Append( var );
						if ( !src.CheckTokenString( "," ) ) {
                            varType = "";
							isConst = false;
							isStatic = false;
							break;
						}
						varType.StripTrailing( "* " );

					} else {

						int bits = 0;

						if ( src.CheckTokenString( ":" ) ) {
							idToken bitSize;
							src.ExpectTokenType( TT_NUMBER, TT_INTEGER, &bitSize );
							bits = bitSize.GetIntValue();
						}

						if ( src.CheckTokenString( "," ) ) {
							idClassVariableInfo var;

							var.name = token;
							var.type = varType;
							var.type.StripTrailing( ' ' );
							var.bits = bits;
							typeInfo->variables.Append( var );
							varType.StripTrailing( "* " );

						} else if ( src.CheckTokenString( ";" ) ) {
							idClassVariableInfo var;

							var.name = token;
							var.type = varType;
							var.type.StripTrailing( ' ' );
							var.bits = bits;
							typeInfo->variables.Append( var );
							varType = "";
							isConst = false;
							isStatic = false;
							break;

						} else {

							varType += token + " ";
							break;
						}
					}

					while( src.CheckTokenString( "*" ) ) {
						varType += "* ";
					}

					if ( !src.ExpectTokenType( TT_NAME, 0, &token ) ) {
						break;
					}
				}
			}
		} else {
			varType += token + " ";
		}
	}
}