/* get a line of input. protected from buffer overrun */ void LibGets(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { ReturnValue->Val->Pointer = PlatformGetLine(Param[0]->Val->Pointer, GETS_BUF_MAX, NULL); if (ReturnValue->Val->Pointer != NULL) { char *EOLPos = strchr(Param[0]->Val->Pointer, '\n'); if (EOLPos != NULL) *EOLPos = '\0'; } }
/* get the next token, without pre-processing */ enum LexToken LexGetRawToken(struct ParseState *Parser, struct Value **Value, int IncPos) { enum LexToken Token = TokenNone; int ValueSize; char *Prompt = NULL; do { /* get the next token */ if (Parser->Pos == NULL && InteractiveHead != NULL) Parser->Pos = InteractiveHead->Tokens; if (Parser->FileName != StrEmpty || InteractiveHead != NULL) { /* skip leading newlines */ while ((Token = (enum LexToken)*(unsigned char *)Parser->Pos) == TokenEndOfLine) { Parser->Line++; Parser->Pos += TOKEN_DATA_OFFSET; } } if (Parser->FileName == StrEmpty && (InteractiveHead == NULL || Token == TokenEOF)) { /* we're at the end of an interactive input token list */ char LineBuffer[LINEBUFFER_MAX]; void *LineTokens; int LineBytes; struct TokenLine *LineNode; if (InteractiveHead == NULL || (unsigned char *)Parser->Pos == &InteractiveTail->Tokens[InteractiveTail->NumBytes-TOKEN_DATA_OFFSET]) { /* get interactive input */ if (LexUseStatementPrompt) { Prompt = INTERACTIVE_PROMPT_STATEMENT; LexUseStatementPrompt = FALSE; } else Prompt = INTERACTIVE_PROMPT_LINE; if (PlatformGetLine(&LineBuffer[0], LINEBUFFER_MAX, Prompt) == NULL) return TokenEOF; /* put the new line at the end of the linked list of interactive lines */ LineTokens = LexAnalyse(StrEmpty, &LineBuffer[0], strlen(LineBuffer), &LineBytes); LineNode = VariableAlloc(Parser, sizeof(struct TokenLine), TRUE); LineNode->Tokens = LineTokens; LineNode->NumBytes = LineBytes; if (InteractiveHead == NULL) { /* start a new list */ InteractiveHead = LineNode; Parser->Line = 1; Parser->CharacterPos = 0; } else InteractiveTail->Next = LineNode; InteractiveTail = LineNode; InteractiveCurrentLine = LineNode; Parser->Pos = LineTokens; } else { /* go to the next token line */ if (Parser->Pos != &InteractiveCurrentLine->Tokens[InteractiveCurrentLine->NumBytes-TOKEN_DATA_OFFSET]) { /* scan for the line */ for (InteractiveCurrentLine = InteractiveHead; Parser->Pos != &InteractiveCurrentLine->Tokens[InteractiveCurrentLine->NumBytes-TOKEN_DATA_OFFSET]; InteractiveCurrentLine = InteractiveCurrentLine->Next) { assert(InteractiveCurrentLine->Next != NULL); } } assert(InteractiveCurrentLine != NULL); InteractiveCurrentLine = InteractiveCurrentLine->Next; assert(InteractiveCurrentLine != NULL); Parser->Pos = InteractiveCurrentLine->Tokens; } Token = (enum LexToken)*(unsigned char *)Parser->Pos; } } while ((Parser->FileName == StrEmpty && Token == TokenEOF) || Token == TokenEndOfLine); Parser->CharacterPos = *((unsigned char *)Parser->Pos + 1); ValueSize = LexTokenSize(Token); if (ValueSize > 0) { /* this token requires a value - unpack it */ if (Value != NULL) { switch (Token) { case TokenStringConstant: LexValue.Typ = CharPtrType; break; case TokenIdentifier: LexValue.Typ = NULL; break; case TokenIntegerConstant: LexValue.Typ = &IntType; break; case TokenCharacterConstant: LexValue.Typ = &CharType; break; #ifndef NO_FP case TokenFPConstant: LexValue.Typ = &FPType; break; #endif default: break; } memcpy((void *)LexValue.Val, (void *)((char *)Parser->Pos + TOKEN_DATA_OFFSET), ValueSize); LexValue.ValOnHeap = FALSE; LexValue.ValOnStack = FALSE; LexValue.IsLValue = FALSE; LexValue.LValueFrom = NULL; *Value = &LexValue; } if (IncPos) Parser->Pos += ValueSize + TOKEN_DATA_OFFSET; } else { if (IncPos && Token != TokenEOF) Parser->Pos += TOKEN_DATA_OFFSET; } #ifdef DEBUG_LEXER printf("Got token=%02x inc=%d pos=%d\n", Token, IncPos, Parser->CharacterPos); #endif assert(Token >= TokenNone && Token <= TokenEndOfFunction); return Token; }