/**
 *  Use for  getting the physical and logical address
 * @param Hal Hardware abstraction layer object
 * @param Node video node
 * @param Address physical address
 * @param Memory logical address
 * @return result of the process
 */
static gceSTATUS LockVideoNode(
        IN gcoHAL Hal,
        IN gcuVIDMEM_NODE_PTR Node,
        IN Bool cacheable,
        OUT gctUINT32 *Address,
        OUT gctPOINTER *Memory) {
    gceSTATUS status;
    gcsHAL_INTERFACE iface;

    gcmASSERT(Address != gcvNULL);
    gcmASSERT(Memory != gcvNULL);
    gcmASSERT(Node != gcvNULL);

    iface.command = gcvHAL_LOCK_VIDEO_MEMORY;
    iface.u.LockVideoMemory.node = Node;
    iface.u.LockVideoMemory.cacheable = cacheable;
    /* Call kernel API. */
    gcmONERROR(gcoHAL_Call(Hal, &iface));

    /* Get allocated node in video memory. */
    *Address = iface.u.LockVideoMemory.address;
    *Memory = iface.u.LockVideoMemory.memory;

OnError:

    return status;
}
/**
 *
 * @param device - to be created
 * @param driver - driver to use the device
 * @return - status of creation
 */
static gctBOOL SetupDevice
(
        OUT Viv2DDevicePtr * device,
        IN Viv2DDriverPtr driver
        ) {
    TRACE_ENTER();
    gceSTATUS status = gcvSTATUS_OK;
    Viv2DDevicePtr pDeviceHandle;
    gctPOINTER mHandle = gcvNULL;
    /*assertions*/
    gcmASSERT(driver != gcvNULL);
    gcmASSERT(*device == gcvNULL);
    /*Allocation*/
    status = gcoOS_Allocate(gcvNULL, sizeof (Viv2DDevice), &mHandle);
    if (status < 0) {
        TRACE_ERROR("Unable to allocate driver, status = %d\n", status);
        TRACE_EXIT(gcvFALSE);
    }
    pDeviceHandle = (Viv2DDevicePtr) mHandle;
    /*Query*/
    status = gcoHAL_QueryChipIdentity(driver->mHal,
            &pDeviceHandle->mChipModel,
            &pDeviceHandle->mChipRevision,
            &pDeviceHandle->mChipFeatures,
            &pDeviceHandle->mChipMinorFeatures);

    if (status != gcvSTATUS_OK) {
        TRACE_ERROR("Unable to query chip Info, status = %d\n", status);
        TRACE_EXIT(gcvFALSE);
    }
    *device = pDeviceHandle;
    TRACE_EXIT(gcvTRUE);
}
/**
 *
 * @param Hal - Hardware abstraction layer object
 * @param Size - Size of the surface in bits
 * @param Pool - To allocate from which pool
 * @param Node - returned allocated video node
 * @return  - result of the process
 */
static gceSTATUS AllocVideoNode(
        IN gcoHAL Hal,
        IN OUT gctUINT_PTR Size,
        IN OUT gcePOOL *Pool,
        IN gceSURF_TYPE surftype,
        OUT gcuVIDMEM_NODE_PTR *Node) {
    gcsHAL_INTERFACE iface;
    gceSTATUS status;

    gcmASSERT(Pool != gcvNULL);
    gcmASSERT(Size != gcvNULL);
    gcmASSERT(Node != gcvNULL);

    iface.command = gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY;
    iface.u.AllocateLinearVideoMemory.bytes = *Size;
    iface.u.AllocateLinearVideoMemory.alignment = 64;
    iface.u.AllocateLinearVideoMemory.pool = *Pool;
    iface.u.AllocateLinearVideoMemory.type = surftype;

    /* Call kernel API. */
    gcmONERROR(gcoHAL_Call(Hal, &iface));

    /* Get allocated node in video memory. */
    *Node = iface.u.AllocateLinearVideoMemory.node;
    *Pool = iface.u.AllocateLinearVideoMemory.pool;
    *Size = iface.u.AllocateLinearVideoMemory.bytes;

OnError:

    return status;
}
gctINT
slScanConvToUnsignedType(
IN sloCOMPILER Compiler,
IN gctUINT LineNo,
IN gctUINT StringNo,
IN gctSTRING Symbol,
OUT slsLexToken * Token
)
{
	gcmASSERT(Token);
	Token->lineNo	= LineNo;
	Token->stringNo	= StringNo;

	/* Check as a reserved keyword */
	switch(_SearchKeyword(Symbol)) {
	case T_INT:
		Token->type = T_UINT;
		break;

	default:
		gcmASSERT(0);
		return T_EOF;
	}

	gcmVERIFY_OK(sloCOMPILER_Dump(Compiler,
				      slvDUMP_SCANNER,
				      "<TOKEN line=\"%d\" string=\"%d\" type=\"keyword\" symbol=\"%s\" />",
				      LineNo,
				      StringNo,
				      Symbol));
	return T_UINT;
}
void vgsMEMORYMANAGER_Free(
	IN vgsMEMORYMANAGER_PTR Manager,
	IN gctPOINTER Pointer
	)
{
	vgsMEMORYITEM_PTR item;

	/* Verify arguments. */
	gcmASSERT(Manager != gcvNULL);
	gcmASSERT(Pointer != gcvNULL);

	/* Get the item pointer. */
	item = (vgsMEMORYITEM_PTR) Pointer - 1;

	/* Update allocated items count. */
#if vgvVALIDATE_MEMORY_MANAGER
	gcmASSERT(_IsValidItem(Manager, item));
	gcmASSERT(_IsAllocatedItem(Manager, item));
	gcmASSERT(Manager->allocatedCount > 0);
	Manager->allocatedCount -= 1;
#endif

	/* Add to the free item list. */
	item->next = Manager->firstFree;
	Manager->firstFree = item;
}
gctINT
slScanHexIntConstant(
	IN sloCOMPILER Compiler,
	IN gctUINT LineNo,
	IN gctUINT StringNo,
	IN gctSTRING Text,
	OUT slsLexToken * Token
	)
{
    gctINT index = 2;

	gcmASSERT(Token);

	Token->lineNo			= LineNo;
	Token->stringNo			= StringNo;
	Token->type			= T_INTCONSTANT;
	Token->u.constant.intValue	= StringToIntConstant(Compiler, LineNo, StringNo, Text, 16, &index);
    gcmASSERT(Text[index] == '\0');

	gcmVERIFY_OK(sloCOMPILER_Dump(
								Compiler,
								slvDUMP_SCANNER,
								"<TOKEN line=\"%d\" string=\"%d\" type=\"intConstant\""
								" format=\"hexadecimal\" value=\"%d\" />",
								LineNo,
								StringNo,
								Token->u.constant.intValue));

	return T_INTCONSTANT;
}
gceSTATUS vgfDereferenceObject(
	vgsCONTEXT_PTR Context,
	vgsOBJECT_PTR * Object
	)
{
	gceSTATUS status = gcvSTATUS_OK;

	gcmASSERT(Context != gcvNULL);
	gcmASSERT(Object != gcvNULL);

	do
	{
		/* Get a shortcut to the object. */
		vgsOBJECT_PTR object = *Object;

		/* Already destroyed? */
		if (object == gcvNULL)
		{
			break;
		}

		/* Valid reference count? */
		if (object->referenceCount < 1)
		{
			gcmFATAL("Invalid reference count found.");
			status = gcvSTATUS_INVALID_OBJECT;
			break;
		}

		/* Decrement the reference count. */
		object->referenceCount--;

		/* Time to destroy? */
		if (object->referenceCount == 0)
		{
			vgsOBJECT_LIST_PTR objectList;

			/* Get a shortcut to the object list. */
			objectList = &Context->objectCache->cache[object->type];

			/* Call the destructor. */
			gcmASSERT(objectList->destructor != gcvNULL);
			gcmERR_BREAK(objectList->destructor(Context, object));

			/* Remove the object from the cache. */
			gcmERR_BREAK(vgfObjectCacheRemove(Context, object));

			/* Free the object. */
			gcmERR_BREAK(gcoOS_Free(Context->os, object));

			/* Reset the pointer. */
			*Object = gcvNULL;
		}
	}
	while (gcvFALSE);

	/* Return status. */
	return status;
}
gceSTATUS
ppoPREPROCESSOR_MacroExpand_6_ExpandHeadTail(
    ppoPREPROCESSOR     PP,
    ppoINPUT_STREAM     *IS,
    ppoTOKEN            *HeadTail,
    ppoTOKEN            *ExpandHeadTail,
    ppoTOKEN            ID,
    ppoMACRO_SYMBOL     MS
    )
{
    gctINT real_argc = 0;
    ppoMACRO_SYMBOL ms = MS;

    while (real_argc < ms->argc)
    {
        gcmASSERT(
            ((HeadTail[real_argc*2] == gcvNULL) && (HeadTail[real_argc*2 + 1] == gcvNULL))
            ||
            ((HeadTail[real_argc*2] != gcvNULL) && (HeadTail[real_argc*2 + 1] != gcvNULL))
            );

        if(HeadTail[real_argc*2] != gcvNULL)
        {
            HeadTail[real_argc*2+1]->inputStream.base.node.prev = gcvNULL;

            gcmTRACE(gcvLEVEL_VERBOSE,  "ME : expand the %dth real-arg ", real_argc);

            ppoPREPROCESSOR_ArgsMacroExpand(
                PP,
                &(HeadTail[real_argc*2]),
                &(ExpandHeadTail[real_argc*2]),
                &(ExpandHeadTail[real_argc*2+1])
                );

            gcmASSERT(HeadTail[real_argc*2] == gcvNULL);

            gcmTRACE(gcvLEVEL_VERBOSE, "ME : the %dth real-arg expanded.", real_argc);
        }
        else
        {
            gcmTRACE(gcvLEVEL_VERBOSE, "ME : no real-arg at %d",real_argc);

            gcmASSERT(
                ExpandHeadTail[real_argc*2] == gcvNULL
                &&
                ExpandHeadTail[real_argc*2+1] == gcvNULL
                );
        }

        ++real_argc;
    }

    gcmTRACE(gcvLEVEL_VERBOSE, "ME : check the HeadTail buffer");

    return gcvSTATUS_OK;
}
void
_glshDereferenceRenderbuffer(
    GLContext Context,
    GLRenderbuffer Renderbuffer
    )
{
    gcmASSERT((Renderbuffer->object.reference - 1) >= 0);

    if (--Renderbuffer->object.reference == 0)
    {
        if (Renderbuffer->surface != gcvNULL)
        {
            if (Renderbuffer->combined == gcvNULL)
            {
                gcmVERIFY_OK(gcoSURF_Destroy(Renderbuffer->surface));
            }
            else
            {
                Renderbuffer->combined->combined = gcvNULL;
            }
        }

        gcmVERIFY_OK(gcmOS_SAFE_FREE(gcvNULL, Renderbuffer));
    }
}
/* Otherwise you get surface from the pool, you have not to allocate the surface */
static GenericSurfacePtr GrabSurfFromPool(gctUINT alignedwidth, gctUINT alignedheight, gctUINT bytesPerPixel)
{
	PGSURFPOOL pnextnode = NULL;
	GenericSurfacePtr pret = NULL;
	gctUINT size = 0;


	SETPOOL(alignedwidth, alignedheight, bytesPerPixel);

	if ( __gpoolhead->pfirst == NULL )
	{
		gcmASSERT( __gpoolhead->num == 0 );
		return NULL;
	}

	size = alignedwidth * alignedheight * bytesPerPixel;

	pnextnode = __gpoolhead->pfirst;
	while ( pnextnode )
	{
		if ( pnextnode->surface->mVideoNode.mSizeInBytes >= size )
		{
			if ( pnextnode->pnext )
				pnextnode->pnext->prev = pnextnode->prev;

			pnextnode->prev->pnext = pnextnode->pnext;

			if ( pnextnode == __gpoolhead->pfirst)
			{
				__gpoolhead->pfirst = pnextnode->pnext;
				if ( pnextnode->pnext)
				pnextnode->pnext->prev = __gpoolhead->pfirst;
			}

			if (pnextnode == __gpoolhead->plast )
				if ( __gpoolhead->pfirst == NULL)
					__gpoolhead->plast = NULL;
				else
					__gpoolhead->plast = pnextnode->prev;

			pret = pnextnode->surface;

			__gpoolhead->num--;

			free(pnextnode);
			break;
		}

		pnextnode = pnextnode->pnext;

	}

#ifdef TEST_POOL
	if ( !TestSurfPool() )
		fprintf(stderr,"Surf Pool Gets ERR when grabbing node \n");
#endif

	return pret;

}
gceSTATUS
ppoPREPROCESSOR_MacroExpand_0_SelfContain(
    ppoPREPROCESSOR     PP,
    ppoINPUT_STREAM     *IS,
    ppoTOKEN            *Head,
    ppoTOKEN            *End,
    gctBOOL             *AnyExpanationHappened,
    gctBOOL             *MatchCase,
    ppoTOKEN            *ID)
{
    gceSTATUS status = gcvSTATUS_INVALID_DATA;

    ppoTOKEN id = gcvNULL;

    gctBOOL inhs = gcvFALSE;

    gcmONERROR(
        (*IS)->GetToken(PP, IS, &id, !ppvICareWhiteSpace)
        );

    gcmASSERT(id && id->type == ppvTokenType_ID);

    *ID = id;

    gcmTRACE(gcvLEVEL_VERBOSE, "ME : Begin to process %s.", id->poolString);

    gcmONERROR(
        ppoHIDE_SET_LIST_ContainSelf(PP, id, &inhs)
        );

    if (inhs == gcvTRUE)
    {
        gcmTRACE(gcvLEVEL_VERBOSE, "ME : self-contain.",id->poolString);

        *Head = id;
        *End  = id;
        *AnyExpanationHappened = gcvFALSE;
        *MatchCase = gcvTRUE;

        return gcvSTATUS_OK;
    }
    else
    {
        gcmTRACE(gcvLEVEL_VERBOSE, "ME : not self-contain.",id->poolString);

        *Head = gcvNULL;
        *End  = gcvNULL;
        *AnyExpanationHappened = gcvFALSE;
        *MatchCase = gcvFALSE;

        return gcvSTATUS_OK;
    }
OnError:
    if (id != gcvNULL)
    {
        gcmVERIFY_OK(ppoTOKEN_Destroy(PP, id));
        id = gcvNULL;
    }
    return status;
}
static gctINT
_SearchKeyword(
	IN gctCONST_STRING Symbol
	)
{
	gctINT		low, mid, high;
	gceSTATUS	result;

	low = 0;
	high = KeywordCount - 1;

	while (low <= high)
	{
		mid = (low + high) / 2;

		result = gcoOS_StrCmp(Symbol, KeywordTable[mid].symbol);

		if (result == gcvSTATUS_SMALLER)
		{
			high	= mid - 1;
		}
		else if (result == gcvSTATUS_LARGER)
		{
			low		= mid + 1;
		}
		else
		{
			gcmASSERT(gcmIS_SUCCESS(result));

			return KeywordTable[mid].token;
		}
	}

	return T_NOT_KEYWORD;
}
gctINT
slScanOperator(
	IN sloCOMPILER Compiler,
	IN gctUINT LineNo,
	IN gctUINT StringNo,
	IN gctSTRING Text,
	IN gctINT tokenType,
	OUT slsLexToken * Token
	)
{
	gcmASSERT(Token);

	Token->lineNo			= LineNo;
	Token->stringNo			= StringNo;
	Token->type				= tokenType;
	Token->u.operator		= tokenType;

	gcmVERIFY_OK(sloCOMPILER_Dump(
								Compiler,
								slvDUMP_SCANNER,
								"<TOKEN line=\"%d\" string=\"%d\""
								" type=\"operator\" symbol=\"%s\" />",
								LineNo,
								StringNo,
								Text));

	return tokenType;
}
gctINT
slScanBoolConstant(
	IN sloCOMPILER Compiler,
	IN gctUINT LineNo,
	IN gctUINT StringNo,
	IN gctBOOL Value,
	OUT slsLexToken * Token
	)
{
	gcmASSERT(Token);

	Token->lineNo			= LineNo;
	Token->stringNo			= StringNo;
	Token->type			= T_BOOLCONSTANT;
	Token->u.constant.boolValue	= Value;

	gcmVERIFY_OK(sloCOMPILER_Dump(
								Compiler,
								slvDUMP_SCANNER,
								"<TOKEN line=\"%d\" string=\"%d\" type=\"boolConstant\" value=\"%s\" />",
								LineNo,
								StringNo,
								(Token->u.constant.boolValue)? "true" : "false"));

	return T_BOOLCONSTANT;
}
gctINT
slScanFloatConstant(
	IN sloCOMPILER Compiler,
	IN gctUINT LineNo,
	IN gctUINT StringNo,
	IN gctSTRING Text,
	OUT slsLexToken * Token
	)
{
	gcmASSERT(Token);

	Token->lineNo			= LineNo;
	Token->stringNo			= StringNo;
	Token->type			= T_FLOATCONSTANT;

	gcmVERIFY_OK(gcoOS_StrToFloat(Text, &Token->u.constant.floatValue));

	gcmVERIFY_OK(sloCOMPILER_Dump(
								Compiler,
								slvDUMP_SCANNER,
								"<TOKEN line=\"%d\" string=\"%d\" type=\"floatConstant\""
								" value=\"%f\" />",
								LineNo,
								StringNo,
								Token->u.constant.floatValue));

	return T_FLOATCONSTANT;
}
static gctBOOL
OutputShaderData(
    IN gcoOS Os,
    IN gctCONST_STRING FileName,
    IN gctSIZE_T Size,
    IN gctCONST_STRING Data
    )
{
    gceSTATUS   status;
    gctSTRING   dataFileName;
    gctSIZE_T   length;
    gctFILE     file;

    gcmASSERT(FileName);

    gcmVERIFY_OK(gcoOS_StrLen(FileName, &length));
    length += 6;
    gcmVERIFY_OK(gcoOS_Allocate(Os, length, (gctPOINTER *) &dataFileName));
    gcmVERIFY_OK(gcoOS_StrCopySafe(dataFileName, length, FileName));
    gcmVERIFY_OK(gcoOS_StrCatSafe(dataFileName, length, ".gcSL"));

    status = gcoOS_Open(Os, dataFileName, gcvFILE_CREATE, &file);

    if (gcmIS_ERROR(status))
    {
        gcoOS_Free(Os, dataFileName);
        printf("*ERROR* Failed to open the data file: %s\n", dataFileName);
        return gcvFALSE;
    }
    gcoOS_Free(Os, dataFileName);

    gcmASSERT(file);
    status = gcoOS_Write(Os, file, Size, Data);

    if (!gcmIS_SUCCESS(status))
    {
        printf("*ERROR* Failed to write the data file: %s\n", dataFileName);
        goto ErrorExit;
    }

    gcmVERIFY_OK(gcoOS_Close(Os, file));
    return gcvTRUE;

ErrorExit:
    gcmVERIFY_OK(gcoOS_Close(Os, file));
    return gcvFALSE;
}
/**
 *
 * @param Hal - Hardware abstraction layer object
 * @param Node - video node
 * @return result of the process
 */
static gceSTATUS FreeVideoNode(
        IN gcoHAL Hal,
        IN gcuVIDMEM_NODE_PTR Node) {
    gcsHAL_INTERFACE iface;

    gcmASSERT(Node != gcvNULL);

    iface.command = gcvHAL_FREE_VIDEO_MEMORY;
    iface.u.FreeVideoMemory.node = Node;

    /* Call kernel API. */
    return gcoHAL_ScheduleEvent(Hal, &iface);
}
/*******************************************************************************
**
**  gcoDUMP_FrameEnd
**
**  Mark the end of a frame.
**
**  INPUT:
**
**      gcoDUMP Dump
**          Pointer to a gcoDUMP object.
**
**  OUTPUT:
**
**      Nothing.
*/
gceSTATUS
gcoDUMP_FrameEnd(
    IN gcoDUMP Dump
    )
{
    gceSTATUS status;
    gcsDUMP_DATA header;
    gctUINT32 pos;

    gcmHEADER_ARG("Dump=0x%x", Dump);

    /* Verify the arguments. */
    gcmVERIFY_OBJECT(Dump, gcvOBJ_DUMP);

    if (Dump->file == gcvNULL)
    {
        /* There is no open dump file. */
        gcmFOOTER_NO();
        return gcvSTATUS_OK;
    }

    do
    {
        /* Get the current position. */
        gcmERR_BREAK(gcoOS_GetPos(gcvNULL, Dump->file, &pos));

        /* Seek to the beginning of the frame. */
        gcmERR_BREAK(gcoOS_SetPos(gcvNULL, Dump->file, Dump->frameStart));

        /* Make sure we got the right byte count. */
        gcmASSERT(pos - Dump->frameStart == Dump->frameLength + sizeof(header));

        /* Update the frame header. */
        header.type    = gcvTAG_FRAME;
        header.length  = Dump->frameLength;
        header.address = ++ Dump->frameCount;

        gcmERR_BREAK(gcoOS_Write(gcvNULL, Dump->file, sizeof(header), &header));

        /* Seek to the end of the file. */
        gcmERR_BREAK(gcoOS_SetPos(gcvNULL, Dump->file, pos));

        /* Mark the frame as ended. */
        Dump->frameStart = 0;
    }
    while (gcvFALSE);

    /* Return the status. */
    gcmFOOTER();
    return status;
}
static gctBOOL
ReadSource(
    IN gcoOS Os,
    IN gctCONST_STRING FileName,
    OUT gctSIZE_T * SourceSize,
    OUT gctSTRING * Source
    )
{
    gceSTATUS   status;
    gctFILE     file;
    gctUINT32   count;
    gctSIZE_T   byteRead;
    gctSTRING   source;

    gcmASSERT(FileName);

    status = gcoOS_Open(Os, FileName, gcvFILE_READ, &file);

    if (gcmIS_ERROR(status))
    {
        printf("*ERROR* Failed to open input file: %s\n", FileName);
        return gcvFALSE;
    }

    gcmVERIFY_OK(gcoOS_Seek(Os, file, 0, gcvFILE_SEEK_END));
    gcmVERIFY_OK(gcoOS_GetPos(Os, file, &count));

    status = gcoOS_Allocate(Os, count + 1, (gctPOINTER *) &source);
    if (!gcmIS_SUCCESS(status))
    {
        printf("*ERROR* Not enough memory\n");
        gcmVERIFY_OK(gcoOS_Close(Os, file));
        return gcvFALSE;
    }

    gcmVERIFY_OK(gcoOS_SetPos(Os, file, 0));
    status = gcoOS_Read(Os, file, count, source, &byteRead);
    if (!gcmIS_SUCCESS(status) || byteRead != count)
    {
        printf("*ERROR* Failed to open input file: %s\n", FileName);
        gcmVERIFY_OK(gcoOS_Close(Os, file));
        return gcvFALSE;
    }

    source[count] = '\0';
    gcmVERIFY_OK(gcoOS_Close(Os, file));

    *SourceSize = count;
    *Source = source;
    return gcvTRUE;
}
gceSTATUS vgfObjectCacheRemove(
	vgsCONTEXT_PTR Context,
	vgsOBJECT_PTR Object
	)
{
	vgsOBJECT_LIST_PTR objectList;

	gctUINT32 index;
	gcmASSERT((Context != gcvNULL) && (Object != gcvNULL));
	gcmASSERT(Context->objectCache != gcvNULL);
	gcmASSERT((Object->type >= 0) && (Object->type < vgvOBJECTTYPE_COUNT));

	/* Get a shortcut to the object list. */
	objectList = &Context->objectCache->cache[Object->type];
	index = Object->name % vgvNAMED_OBJECTS_HASH;

	/* Remove from the chain. */
	if (Object == objectList->head[index])
	{
		objectList->head[index] = Object->next;
	}
	else
	{
		Object->prev->next = Object->next;
	}

	if (Object->next)
	{
		Object->next->prev = Object->prev;
	}

	Object->prev = Object->next = gcvNULL;

	/* Success. */
	return gcvSTATUS_OK;
}
gceSTATUS vgsMEMORYMANAGER_Destroy(
	IN vgsMEMORYMANAGER_PTR Manager
	)
{
	gceSTATUS status;
	vgsMEMORYITEM_PTR current;
	vgsMEMORYITEM_PTR next;

    gcmHEADER_ARG("Manager=0x%x", Manager);

	/* Verify arguments. */
	gcmVERIFY_ARGUMENT(Manager != gcvNULL);

	/* Assume success. */
	status = gcvSTATUS_OK;

	/* Everything has to be freed. */
#if vgvVALIDATE_MEMORY_MANAGER
	gcmASSERT(Manager->allocatedCount == 0);
#endif

	/* Destroy all allocated buffers. */
	while (Manager->firstAllocated)
	{
		/* Get the current buffer. */
		current = Manager->firstAllocated;

		/* Get the next buffer. */
		next = current->next;

		/* Free the current. */
		gcmERR_BREAK(gcoOS_Free(Manager->os, current));

		/* Advance to the next one. */
		Manager->firstAllocated = next;
	}

	/* Success? */
	if (gcmIS_SUCCESS(status))
	{
		status = gcoOS_Free(Manager->os, Manager);
	}

    gcmFOOTER();
	/* Return status. */
	return status;
}
static gctINT
GetShaderType(
    IN gctCONST_STRING FileName
    )
{
    gctCONST_STRING ext;

    gcmASSERT(FileName);

    ext = strrchr(FileName, '.');

    if (ext != gcvNULL)
    {
        if (gcmIS_SUCCESS(gcoOS_StrNCmp(ext, ".frag", 4))) return gcSHADER_TYPE_FRAGMENT;
        if (gcmIS_SUCCESS(gcoOS_StrNCmp(ext, ".vert", 4))) return gcSHADER_TYPE_VERTEX;
    }

    return gcSHADER_TYPE_FRAGMENT;
}
/**
 *
 * @param Hal
 * @param Node
 * @return
 */
static gceSTATUS UnlockVideoNode(
	IN gcoHAL Hal,
	IN gcuVIDMEM_NODE_PTR Node,
	IN gceSURF_TYPE surftype) {

	gcsHAL_INTERFACE iface;
	gceSTATUS status;

	gcmASSERT(Node != gcvNULL);

	iface.command = gcvHAL_UNLOCK_VIDEO_MEMORY;
	iface.u.UnlockVideoMemory.node = Node;
	iface.u.UnlockVideoMemory.type = surftype;
	iface.u.UnlockVideoMemory.asynchroneous = gcvTRUE;

	/* Call the kernel. */
	gcmONERROR(gcoOS_DeviceControl(
				gcvNULL,
				IOCTL_GCHAL_INTERFACE,
				&iface, gcmSIZEOF(iface),
				&iface, gcmSIZEOF(iface)
	));

	/* Success? */
	gcmONERROR(iface.status);

	/* Do we need to schedule an event for the unlock? */
	if (iface.u.UnlockVideoMemory.asynchroneous)
	{
		iface.u.UnlockVideoMemory.asynchroneous = gcvFALSE;
		gcmONERROR(gcoHAL_ScheduleEvent(Hal, &iface));
	}

OnError:
    /* Call kernel API. */
    return gcvSTATUS_FALSE;

}
gceSTATUS
ppoPREPROCESSOR_MacroExpand_7_ParseReplacementList_AddToOut(
    ppoPREPROCESSOR     PP,
    ppoTOKEN            InHead,
    ppoTOKEN            InEnd,
    ppoTOKEN            *OutHead,
    ppoTOKEN            *OutEnd
    )
{
    gcmASSERT(
        (InHead == gcvNULL && InEnd == gcvNULL)
        ||
        (InHead != gcvNULL && InEnd != gcvNULL));

    if(InHead == gcvNULL)
    {
        return gcvSTATUS_OK;
    }

    if ((*OutHead) == gcvNULL)
    {
        *OutHead = InHead;
        *OutEnd  = InEnd;

        InHead->inputStream.base.node.next = gcvNULL;
        if(InEnd)  InEnd->inputStream.base.node.prev  = gcvNULL;
    }
    else
    {
        (*OutEnd)->inputStream.base.node.prev = (void*)InHead;
        InHead->inputStream.base.node.next = (void*)(*OutEnd);
        (*OutEnd) = InEnd;
        InEnd->inputStream.base.node.prev = gcvNULL;
    }

    return gcvSTATUS_OK;
}
gctINT
slScanFieldSelection(
	IN sloCOMPILER Compiler,
	IN gctUINT LineNo,
	IN gctUINT StringNo,
	IN gctSTRING Symbol,
	OUT slsLexToken * Token
	)
{
	gceSTATUS		status;
	sltPOOL_STRING	symbolInPool;

	gcmASSERT(Token);

	Token->lineNo	= LineNo;
	Token->stringNo	= StringNo;

	status = sloCOMPILER_AllocatePoolString(
											Compiler,
											Symbol,
											&symbolInPool);

	if (gcmIS_ERROR(status)) return T_EOF;

	Token->type = T_FIELD_SELECTION;
	Token->u.fieldSelection = symbolInPool;

	gcmVERIFY_OK(sloCOMPILER_Dump(
								Compiler,
								slvDUMP_SCANNER,
								"<TOKEN line=\"%d\" string=\"%d\" type=\"fieldSelection\" symbol=\"%s\" />",
								LineNo,
								StringNo,
								Token->u.fieldSelection));

	return T_FIELD_SELECTION;
}
/*******************************************************************************
**
**  gcoBUFFER_Reserve
**
**  Reserve a number of bytes in the buffer.
**
**  INPUT:
**
**      gcoBUFFER Buffer
**          Pointer to an gcoBUFFER object.
**
**      gctSIZE_T Bytes
**          Number of bytes to reserve.
**
**      gctBOOL Aligned
**          gcvTRUE if the data needs to be aligned to 64-bit.
**
**  OUTPUT:
**
**      gctUINT32_PTR ** AddressHints
**          Pointer to a variable that receives the current position in the
**          state hint array.  gcvNULL is allowed.
**
**      gctPOINTER * Memory
**          Pointer to a variable that will hold the address of location in the
**          buffer that has been reserved.
*/
gceSTATUS
gcoBUFFER_Reserve(
    IN gcoBUFFER Buffer,
    IN gctSIZE_T Bytes,
    IN gctBOOL Aligned,
    OUT gcoCMDBUF * Reserve
    )
{
    gceSTATUS status = gcvSTATUS_OK;
    gcoCMDBUF current;
    gctSIZE_T alignBytes, bytes;
    gctUINT offset;

    gcmHEADER_ARG("Buffer=0x%x Bytes=%lu Aligned=%d Reserve=0x%x",
                  Buffer, Bytes, Aligned, Reserve);

    /* Verify the arguments. */
    gcmVERIFY_OBJECT(Buffer, gcvOBJ_BUFFER);
    gcmDEBUG_VERIFY_ARGUMENT(Reserve != gcvNULL);

    /* Get the current command buffer. */
    current = Buffer->currentCommandBuffer;

    /* Compute the number of aligned bytes. */
    alignBytes = Aligned
               ? ( gcmALIGN(current->offset, Buffer->info.alignment)
                 - current->offset
                 )
               : 0;

    /* Compute the number of required bytes. */
    bytes = Bytes + alignBytes;

    if (bytes > current->free)
    {
        gcsHAL_INTERFACE iface;

        if (bytes > Buffer->maxSize - Buffer->totalReserved)
        {
            /* This just won't fit! */
            gcmFATAL("FATAL: Command of %lu bytes is too big!", Bytes);
            gcmONERROR(gcvSTATUS_OUT_OF_MEMORY);
        }

        /* Sent event to signal when command buffer completes. */
        iface.command            = gcvHAL_SIGNAL;
        iface.u.Signal.signal    = Buffer->signal
                                   [Buffer->currentCommandBufferIndex];
        iface.u.Signal.auxSignal = gcvNULL;
        iface.u.Signal.process   = gcoOS_GetCurrentProcessID();
        iface.u.Signal.fromWhere = gcvKERNEL_COMMAND;

        /* Send event. */
        gcmONERROR(
            gcoHARDWARE_CallEvent(&iface));

        /* Commit current command buffer. */
        gcmONERROR(
            gcoHARDWARE_Commit());

        /* Grab a new command buffer. */
        gcmONERROR(
            gcoBUFFER_GetCMDBUF(Buffer));

        /* Get the pointer. */
        current = Buffer->currentCommandBuffer;

        /* Calculate total bytes again. */
        alignBytes = 0;
        bytes      = Bytes;
    }

    gcmASSERT(current != gcvNULL);
    gcmASSERT(bytes   <= current->free);

    /* Determine the data offset. */
    offset = current->offset + alignBytes;

    /* Update the last reserved location. */
    current->lastReserve = (gctUINT8_PTR) current->logical + offset;
    current->lastOffset  = offset;

    /* Adjust command buffer size. */
    current->offset += bytes;
    current->free   -= bytes;

    /* Set the result. */
    * Reserve = current;

    /* Success. */
    gcmFOOTER();
    return gcvSTATUS_OK;

OnError:
    /* Return the status. */
    gcmFOOTER();
    return status;
}
/*******************************************************************************
**
**  gcoDUMP_Control
**
**  Control dumping.
**
**  INPUT:
**
**      gcoDUMP Dump
**          Pointer to a gcoDUMP object.
**
**      gctSTRING FileName
**          If 'FileName' is not gcvNULL, it points to the filename to be used for
**          capturing all data.  If 'FileName' is gcvNULL, turn off any current
**          capturing.
**
**  OUTPUT:
**
**      Nothing.
*/
gceSTATUS
gcoDUMP_Control(
    IN gcoDUMP Dump,
    IN gctSTRING FileName
    )
{
    gceSTATUS status = gcvSTATUS_OK;
    gcsDUMP_FILE header;
    gctUINT32 pos;

    gcmHEADER_ARG("Dump=0x%x FileName=0x%x", Dump, FileName);

    /* Verify the arguments. */
    gcmVERIFY_OBJECT(Dump, gcvOBJ_DUMP);

    do
    {
        if (FileName != gcvNULL)
        {
            /* Need to create a new dump file. */
            if (Dump->file == gcvNULL)
            {
                /* Create the dump file. */
                gcmERR_BREAK(gcoOS_Open(gcvNULL,
                                    FileName,
                                    gcvFILE_CREATE,
                                    &Dump->file));

                /* Write the file header. */
                header.signature   = gcvDUMP_FILE_SIGNATURE;
                header.length      = Dump->length     = 0;
                header.frames      = Dump->frameCount = 0;

                gcmERR_BREAK(gcoOS_Write(gcvNULL,
                                     Dump->file,
                                     sizeof(header),
                                     &header));

                /* Frame is not yet started. */
                Dump->frameStart = 0;
            }
        }
        else
        {
            /* Need to close any current dump file. */
            if (Dump->file != gcvNULL)
            {
                /* Close any open frame. */
                if (Dump->frameStart != 0)
                {
                    gcoDUMP_FrameEnd(Dump);
                    gcoDUMP_FrameBegin(Dump);
                }

                /* Get the current position. */
                gcmERR_BREAK(gcoOS_GetPos(gcvNULL, Dump->file, &pos));

                /* Seek to the beginnnig of the file. */
                gcmERR_BREAK(gcoOS_SetPos(gcvNULL, Dump->file, 0));

                /* Make sure we have the correct size. */
                gcmASSERT(pos == Dump->length + sizeof(header));

                /* Update the file header. */
                header.signature = gcvDUMP_FILE_SIGNATURE;
                header.length    = Dump->length;
                header.frames    = Dump->frameCount;

                gcmERR_BREAK(gcoOS_Write(gcvNULL,
                                     Dump->file,
                                     sizeof(header),
                                     &header));

                /* Seek to the end of the file. */
                gcmERR_BREAK(gcoOS_SetPos(gcvNULL, Dump->file, pos));

                /* Close the file. */
                gcmERR_BREAK(gcoOS_Close(gcvNULL, Dump->file));

                /* Mark the file as closed. */
                Dump->file = gcvNULL;
            }
        }
    }
    while (gcvFALSE);

    /* Return the status. */
    gcmFOOTER();
    return status;
}
Exemple #28
0
gceSTATUS vgfConvertArc(
	vgsPATHWALKER_PTR Destination,
	gctFLOAT HorRadius,
	gctFLOAT VerRadius,
	gctFLOAT RotAngle,
	gctFLOAT EndX,
	gctFLOAT EndY,
	gctBOOL CounterClockwise,
	gctBOOL Large,
	gctBOOL Relative
	)
{
	gceSTATUS status;
	vgsARCCOORDINATES_PTR arcCoords = gcvNULL;

	do
	{
		gctFLOAT endX, endY;
		gceVGCMD segmentCommand;
		vgsCONTROL_COORD_PTR coords;


		/*******************************************************************
		** Determine the absolute end point coordinates.
		*/

		/* Get a shortcut to the control coordinates. */
		coords = Destination->coords;

		if (Relative)
		{
			endX = EndX + coords->lastX;
			endY = EndY + coords->lastY;
		}
		else
		{
			endX = EndX;
			endY = EndY;
		}

		/* If both of the radiuses are zeros, make a line out of the arc. */
		if ((HorRadius == 0.0f) || (VerRadius == 0.0f) ||
			((endX == coords->lastX) && (endY == coords->lastY)))
		{
			/* Determine the segment command. */
			segmentCommand = Relative
				? gcvVGCMD_ARC_LINE_REL
				: gcvVGCMD_ARC_LINE;

			/* Allocate a new subpath. */
			gcmERR_BREAK(vgsPATHWALKER_StartSubpath(
				Destination, vgmCOMMANDSIZE(2, gctFLOAT), gcePATHTYPE_FLOAT
				));

			/* Write the command. */
			gcmERR_BREAK(vgsPATHWALKER_WriteCommand(
				Destination,
				segmentCommand
				));

			/* Write the coordinates. */
			Destination->set(Destination, EndX);
			Destination->set(Destination, EndY);
		}
		else
		{
			VGfloat phi, cosPhi, sinPhi;
			VGfloat dxHalf, dyHalf;
			VGfloat x1Prime, y1Prime;
			VGfloat rx, ry;
			VGfloat x1PrimeSquare, y1PrimeSquare;
			VGfloat lambda;
			VGfloat rxSquare, rySquare;
			VGint sign;
			VGfloat sq, signedSq;
			VGfloat cxPrime, cyPrime;
			VGfloat theta1, thetaSpan;
			VGint segs;
			VGfloat theta, ax, ay, x, y;
			VGfloat controlX, controlY, anchorX, anchorY;
			VGfloat lastX, lastY;
			gctUINT bufferSize;


			/*******************************************************************
			** Converting.
			*/

			phi = RotAngle / 180.0f * vgvPI;
			cosPhi = gcmCOSF(phi);
			sinPhi = gcmSINF(phi);

			if (Relative)
			{
				dxHalf = - EndX / 2.0f;
				dyHalf = - EndY / 2.0f;
			}
			else
			{
				dxHalf = (coords->lastX - endX) / 2.0f;
				dyHalf = (coords->lastY - endY) / 2.0f;
			}

			x1Prime =  cosPhi * dxHalf + sinPhi * dyHalf;
			y1Prime = -sinPhi * dxHalf + cosPhi * dyHalf;

			rx = gcmFABSF(HorRadius);
			ry = gcmFABSF(VerRadius);

			x1PrimeSquare = x1Prime * x1Prime;
			y1PrimeSquare = y1Prime * y1Prime;

			lambda = x1PrimeSquare / (rx * rx) + y1PrimeSquare / (ry * ry);
			if (lambda > 1.0f)
			{
				rx *= gcmSQRTF(lambda);
				ry *= gcmSQRTF(lambda);
			}

			rxSquare = rx * rx;
			rySquare = ry * ry;

			sign     = (Large == CounterClockwise) ? -1 : 1;
			sq       = ( rxSquare * rySquare
					   - rxSquare * y1PrimeSquare
					   - rySquare * x1PrimeSquare
					   )
					   /
					   ( rxSquare * y1PrimeSquare
					   + rySquare * x1PrimeSquare
					   );
			signedSq = sign * ((sq < 0) ? 0 : gcmSQRTF(sq));
			cxPrime  = signedSq *  (rx * y1Prime / ry);
			cyPrime  = signedSq * -(ry * x1Prime / rx);

			theta1 = _Angle(1, 0, (x1Prime - cxPrime) / rx, (y1Prime - cyPrime) / ry);
			theta1 = gcmFMODF(theta1, 2 * vgvPI);

			thetaSpan = _Angle(( x1Prime - cxPrime) / rx, ( y1Prime - cyPrime) / ry,
							   (-x1Prime - cxPrime) / rx, (-y1Prime - cyPrime) / ry);

			if (!CounterClockwise && (thetaSpan > 0))
			{
				thetaSpan -= 2 * vgvPI;
			}
			else if (CounterClockwise && (thetaSpan < 0))
			{
				thetaSpan += 2 * vgvPI;
			}

			thetaSpan = gcmFMODF(thetaSpan, 2 * vgvPI);


			/*******************************************************************
			** Drawing.
			*/

			segs  = (VGint) (gcmCEILF(gcmFABSF(thetaSpan) / (45.0f / 180.0f * vgvPI)));
			gcmASSERT(segs > 0);

			theta = thetaSpan / segs;

			ax = coords->lastX - gcmCOSF(theta1) * rx;
			ay = coords->lastY - gcmSINF(theta1) * ry;

			/* Determine the segment command. */
			segmentCommand = Relative
				? gcvVGCMD_ARC_QUAD_REL
				: gcvVGCMD_ARC_QUAD;

			/* Determine the size of the buffer required. */
			bufferSize = (1 + 2 * 2) * gcmSIZEOF(gctFLOAT) * segs;

			/* Allocate a new subpath. */
			gcmERR_BREAK(vgsPATHWALKER_StartSubpath(
				Destination, bufferSize, gcePATHTYPE_FLOAT
				));

			/* Set initial last point. */
			lastX = coords->lastX;
			lastY = coords->lastY;

			while (segs-- > 0)
			{
				theta1 += theta;

				controlX = ax + gcmCOSF(theta1 - (theta / 2.0f)) * rx / gcmCOSF(theta / 2.0f);
				controlY = ay + gcmSINF(theta1 - (theta / 2.0f)) * ry / gcmCOSF(theta / 2.0f);

				anchorX = ax + gcmCOSF(theta1) * rx;
				anchorY = ay + gcmSINF(theta1) * ry;

				if (RotAngle != 0)
				{
					x = coords->lastX + cosPhi * (controlX - coords->lastX) - sinPhi * (controlY - coords->lastY);
					y = coords->lastY + sinPhi * (controlX - coords->lastX) + cosPhi * (controlY - coords->lastY);
					controlX = x;
					controlY = y;

					x = coords->lastX + cosPhi * (anchorX - coords->lastX) - sinPhi * (anchorY - coords->lastY);
					y = coords->lastY + sinPhi * (anchorX - coords->lastX) + cosPhi * (anchorY - coords->lastY);
					anchorX = x;
					anchorY = y;
				}

				if (segs == 0)
				{
					/* Use end point directly to avoid accumulated errors. */
					anchorX = endX;
					anchorY = endY;
				}

				/* Adjust relative coordinates. */
				if (Relative)
				{
					VGfloat nextLastX = anchorX;
					VGfloat nextLastY = anchorY;

					controlX -= lastX;
					controlY -= lastY;

					anchorX -= lastX;
					anchorY -= lastY;

					lastX = nextLastX;
					lastY = nextLastY;
				}

				/* Write the command. */
				gcmERR_BREAK(vgsPATHWALKER_WriteCommand(
					Destination, segmentCommand
					));

				/* Set the coordinates. */
				Destination->set(Destination, controlX);
				Destination->set(Destination, controlY);
				Destination->set(Destination, anchorX);
				Destination->set(Destination, anchorY);
			}
		}

		/* Store ARC coordinates. */
		gcmERR_BREAK(vgsMEMORYMANAGER_Allocate(
			Destination->arcCoordinates,
			(gctPOINTER *) &arcCoords
			));

		arcCoords->large            = Large;
		arcCoords->counterClockwise = CounterClockwise;
		arcCoords->horRadius        = HorRadius;
		arcCoords->verRadius        = VerRadius;
		arcCoords->rotAngle         = RotAngle;
		arcCoords->endX             = EndX;
		arcCoords->endY             = EndY;

		/* Store the pointer to ARC coordinates. */
		Destination->currPathData->extraManager = Destination->arcCoordinates;
		Destination->currPathData->extra        = arcCoords;

		/* Update the control coordinates. */
		coords->lastX    = endX;
		coords->lastY    = endY;
		coords->controlX = endX;
		coords->controlY = endY;

		/* Success. */
		return gcvSTATUS_OK;
	}
	while (gcvFALSE);

	/* Roll back. */
	vgsPATHWALKER_Rollback(Destination);

	/* Return status. */
	return status;
}
static gcSHADER
CompileFile(
    IN gcoOS Os,
    IN gctCONST_STRING FileName,
    IN gcoHAL Hal,
    IN gctUINT Option,
    IN gctBOOL DumpLog,
    IN gctBOOL DumpCompiledShader
    )
{
    gceSTATUS   status;
    gctINT      shaderType;
    gctSIZE_T   sourceSize;
    gctSTRING   source          = gcvNULL;
    gcSHADER    binary;
    gctSTRING   log             = gcvNULL;
    gctSIZE_T   bufferSize;
    gctSTRING   buffer;
    gctSTRING   dataFileName    = gcvNULL;
    gctSIZE_T   length;
    gctFILE     logFile         = gcvNULL;

    gcmASSERT(FileName);

    shaderType = GetShaderType(FileName);

    if (!ReadSource(Os, FileName, &sourceSize, &source)) return gcvNULL;

    status = gcCompileShader(Hal,
                             shaderType,
                             sourceSize, source,
                             &binary,
                             &log);

    if (log != gcvNULL)
    {
        printf("<LOG>\n");
        printf("%s", log);
        printf("</LOG>\n");
    }

    if (gcmIS_ERROR(status))
    {
        gcmASSERT(binary == gcvNULL);
        binary = gcvNULL;

        printf("*ERROR* Failed to compile %s (error: %d)\n", FileName, status);
        goto Exit;
    }

    gcmASSERT(binary != gcvNULL);

    if (DumpLog)
    {
        gcmVERIFY_OK(gcoOS_StrLen(FileName, &length));
        length += 5;
        gcmVERIFY_OK(gcoOS_Allocate(Os, length, (gctPOINTER *) &dataFileName));
        gcmVERIFY_OK(gcoOS_StrCopySafe(dataFileName, length, FileName));
        gcmVERIFY_OK(gcoOS_StrCatSafe(dataFileName, length, ".log"));

        status = gcoOS_Open(Os, dataFileName, gcvFILE_CREATETEXT, &logFile);
        if (gcmIS_ERROR(status))
        {
            logFile = gcvNULL;

            printf("*ERROR* Failed to open the log file: %s\n", dataFileName);
        }
        gcoOS_Free(Os, dataFileName);
    }

    gcmVERIFY_OK(gcSHADER_SetOptimizationOption(binary, Option));

    status = gcOptimizeShader(binary, logFile);

    if (!gcmIS_SUCCESS(status))
    {
        printf("*ERROR* Failed to optimize %s (error: %d)\n", FileName, status);
    }

    if (logFile != gcvNULL)
    {
        gcmVERIFY_OK(gcoOS_Close(Os, logFile));
    }

    if (DumpCompiledShader)
    {
        status = gcSHADER_Save(binary, gcvNULL, &bufferSize);
        if (gcmIS_ERROR(status))
        {
            printf("*ERROR* Failed to get the buffer size of the shader\n");
            goto Exit;
        }

        status = gcoOS_Allocate(Os, bufferSize, (gctPOINTER *) &buffer);
        if (!gcmIS_SUCCESS(status))
        {
            printf("*ERROR* Not enough memory\n");
            goto Exit;
        }

        status = gcSHADER_Save(binary, buffer, &bufferSize);
        if (status != gcvSTATUS_OK)
        {
            printf("*ERROR* Failed to get the buffer size of the shader\n");
            gcoOS_Free(Os, buffer);
            goto Exit;
        }

        OutputShaderData(Os, FileName, bufferSize, buffer);

        gcoOS_Free(Os, buffer);
    }


Exit:
    if (DumpLog && log != gcvNULL)
    {
        printf("**************** Compile Log ****************");
        printf("%s", log);
        printf("*********************************************");
    }

    if (log != gcvNULL) gcoOS_Free(Os, log);

    if (source != gcvNULL) gcoOS_Free(Os, source);

    return binary;
}
static gctINT32
StringToIntConstant(
	IN sloCOMPILER Compiler,
	IN gctUINT LineNo,
	IN gctUINT StringNo,
	IN gctSTRING String,
	IN gctINT Base,
	IN OUT gctINT * Index
	)
{
	gctINT orgIndex = *Index;
    gctBOOL error = gcvFALSE;
	gctINT32 result = 0, digit = 0;
	gctCHAR ch;

	gcmASSERT(String);
	gcmASSERT(Index);
	gcmASSERT((Base == 8) || (Base == 10) || (Base == 16));

	for (; gcvTRUE; (*Index)++)
	{
		ch = String[*Index];

		switch (Base)
		{
		case 8:
			if ((ch >= '0') && (ch <= '7')) digit = ch - '0';
			else goto EXIT;
			break;

		case 10:
			if ((ch >= '0') && (ch <= '9')) digit = ch - '0';
			else goto EXIT;
			break;

		case 16:
			if ((ch >= 'a') && (ch <= 'f'))			digit = ch - 'a' + 10;
			else if ((ch >= 'A') && (ch <= 'F'))	digit = ch - 'A' + 10;
			else if ((ch >= '0') && (ch <= '9'))	digit = ch - '0';
			else goto EXIT;
			break;

		default: gcmASSERT(0);
		}

		if (error) continue;

		if (result > ((SL_INT_MAX - digit) / Base))
		{
            error = gcvTRUE;

			gcmVERIFY_OK(sloCOMPILER_Report(
											Compiler,
											LineNo,
											StringNo,
											slvREPORT_ERROR,
											"too large %s integer: %s",
											(Base == 8)?
												"octal" : ((Base == 10)? "decimal" : "hexadecimal"),
											String + orgIndex));
        }
		else
		{
            result = result * Base + digit;
        }
    }

EXIT:
    return result;
}