/* free and/or pop the top value off the stack. Var must be the top value on the stack! */ void VariableStackPop(struct ParseState *Parser, struct Value *Var) { int Success; #ifdef DEBUG_HEAP if (Var->ValOnStack) printf("popping %ld at 0x%lx\n", (unsigned long)(sizeof(struct Value) + TypeSizeValue(Var, FALSE)), (unsigned long)Var); #endif if (Var->ValOnHeap) { if (Var->Val != NULL) HeapFreeMem(Var->Val); Success = HeapPopStack(Var, sizeof(struct Value)); /* free from heap */ } else if (Var->ValOnStack) Success = HeapPopStack(Var, sizeof(struct Value) + TypeSizeValue(Var, FALSE)); /* free from stack */ else Success = HeapPopStack(Var, sizeof(struct Value)); /* value isn't our problem */ if (!Success) ProgramFail(Parser, "stack underrun"); }
/* produce tokens from the lexer and return a heap buffer with the result - used for scanning */ void *LexTokenise(struct LexState *Lexer, int *TokenLen) { enum LexToken Token; void *HeapMem; struct Value *GotValue; int MemUsed = 0; int ValueSize; int ReserveSpace = (Lexer->End - Lexer->Pos) * 4 + 16; void *TokenSpace = HeapAllocStack(ReserveSpace); char *TokenPos = (char *)TokenSpace; int LastCharacterPos = 0; if (TokenSpace == NULL) LexFail(Lexer, "out of memory"); do { /* store the token at the end of the stack area */ Token = LexScanGetToken(Lexer, &GotValue); #ifdef DEBUG_LEXER printf("Token: %02x\n", Token); #endif *(unsigned char *)TokenPos = Token; TokenPos++; MemUsed++; *(unsigned char *)TokenPos = (unsigned char)LastCharacterPos; TokenPos++; MemUsed++; ValueSize = LexTokenSize(Token); if (ValueSize > 0) { /* store a value as well */ memcpy((void *)TokenPos, (void *)GotValue->Val, ValueSize); TokenPos += ValueSize; MemUsed += ValueSize; } LastCharacterPos = Lexer->CharacterPos; } while (Token != TokenEOF); HeapMem = HeapAllocMem(MemUsed); if (HeapMem == NULL) LexFail(Lexer, "out of memory"); assert(ReserveSpace >= MemUsed); memcpy(HeapMem, TokenSpace, MemUsed); HeapPopStack(TokenSpace, ReserveSpace); #ifdef DEBUG_LEXER { int Count; printf("Tokens: "); for (Count = 0; Count < MemUsed; Count++) printf("%02x ", *((unsigned char *)HeapMem+Count)); printf("\n"); } #endif if (TokenLen) *TokenLen = MemUsed; return HeapMem; }
/* get a string constant - used while scanning */ enum LexToken LexGetStringConstant(struct LexState *Lexer, struct Value *Value, char EndChar) { int Escape = FALSE; const char *StartPos = Lexer->Pos; const char *EndPos; char *EscBuf; char *EscBufPos; char *RegString; struct Value *ArrayValue; while (Lexer->Pos != Lexer->End && (*Lexer->Pos != EndChar || Escape)) { /* find the end */ if (Escape) { if (*Lexer->Pos == '\r' && Lexer->Pos+1 != Lexer->End) Lexer->Pos++; if (*Lexer->Pos == '\n' && Lexer->Pos+1 != Lexer->End) { Lexer->Line++; Lexer->Pos++; Lexer->CharacterPos = 0; Lexer->EmitExtraNewlines++; } Escape = FALSE; } else if (*Lexer->Pos == '\\') Escape = TRUE; LEXER_INC(Lexer); } EndPos = Lexer->Pos; EscBuf = HeapAllocStack(EndPos - StartPos); if (EscBuf == NULL) LexFail(Lexer, "out of memory"); for (EscBufPos = EscBuf, Lexer->Pos = StartPos; Lexer->Pos != EndPos;) *EscBufPos++ = LexUnEscapeCharacter(&Lexer->Pos, EndPos); /* try to find an existing copy of this string literal */ RegString = TableStrRegister2(EscBuf, EscBufPos - EscBuf); HeapPopStack(EscBuf, EndPos - StartPos); ArrayValue = VariableStringLiteralGet(RegString); if (ArrayValue == NULL) { /* create and store this string literal */ ArrayValue = VariableAllocValueAndData(NULL, 0, FALSE, NULL, TRUE); ArrayValue->Typ = CharArrayType; ArrayValue->Val = (union AnyValue *)RegString; VariableStringLiteralDefine(RegString, ArrayValue); } /* create the the pointer for this char* */ Value->Typ = CharPtrType; Value->Val->Pointer = RegString; if (*Lexer->Pos == EndChar) LEXER_INC(Lexer); return TokenStringConstant; }