/* parse a statement */ enum ParseResult ParseStatement(struct ParseState *Parser, int CheckTrailingSemicolon) { struct Value *CValue; struct Value *LexerValue; struct Value *VarValue; int Condition; struct ParseState PreState; enum LexToken Token; /* if we're debugging, check for a breakpoint */ if (Parser->DebugMode && Parser->Mode == RunModeRun) DebugCheckStatement(Parser); /* take note of where we are and then grab a token to see what statement we have */ ParserCopy(&PreState, Parser); Token = LexGetToken(Parser, &LexerValue, TRUE); switch (Token) { case TokenEOF: return ParseResultEOF; case TokenIdentifier: /* might be a typedef-typed variable declaration or it might be an expression */ if (VariableDefined(Parser->pc, LexerValue->Val->Identifier)) { VariableGet(Parser->pc, Parser, LexerValue->Val->Identifier, &VarValue); if (VarValue->Typ->Base == Type_Type) { *Parser = PreState; ParseDeclaration(Parser, Token); break; } } else { /* it might be a goto label */ enum LexToken NextToken = LexGetToken(Parser, NULL, FALSE); if (NextToken == TokenColon) { /* declare the identifier as a goto label */ LexGetToken(Parser, NULL, TRUE); if (Parser->Mode == RunModeGoto && LexerValue->Val->Identifier == Parser->SearchGotoLabel) Parser->Mode = RunModeRun; CheckTrailingSemicolon = FALSE; break; } #ifdef FEATURE_AUTO_DECLARE_VARIABLES else /* new_identifier = something */ { /* try to guess type and declare the variable based on assigned value */ if (NextToken == TokenAssign && !VariableDefinedAndOutOfScope(Parser->pc, LexerValue->Val->Identifier)) { if (Parser->Mode == RunModeRun) { struct Value *CValue; char* Identifier = LexerValue->Val->Identifier; LexGetToken(Parser, NULL, TRUE); if (!ExpressionParse(Parser, &CValue)) { ProgramFail(Parser, "expected: expression"); } #if 0 PRINT_SOURCE_POS; PlatformPrintf(Parser->pc->CStdOut, "%t %s = %d;\n", CValue->Typ, Identifier, CValue->Val->Integer); printf("%d\n", VariableDefined(Parser->pc, Identifier)); #endif VariableDefine(Parser->pc, Parser, Identifier, CValue, CValue->Typ, TRUE); break; } } } #endif } /* else fallthrough to expression */ /* no break */ case TokenAsterisk: case TokenAmpersand: case TokenIncrement: case TokenDecrement: case TokenOpenBracket: *Parser = PreState; ExpressionParse(Parser, &CValue); if (Parser->Mode == RunModeRun) VariableStackPop(Parser, CValue); break; case TokenLeftBrace: ParseBlock(Parser, FALSE, TRUE); CheckTrailingSemicolon = FALSE; break; case TokenIf: if (LexGetToken(Parser, NULL, TRUE) != TokenOpenBracket) ProgramFail(Parser, "'(' expected"); Condition = ExpressionParseInt(Parser); if (LexGetToken(Parser, NULL, TRUE) != TokenCloseBracket) ProgramFail(Parser, "')' expected"); if (ParseStatementMaybeRun(Parser, Condition, TRUE) != ParseResultOk) ProgramFail(Parser, "statement expected"); if (LexGetToken(Parser, NULL, FALSE) == TokenElse) { LexGetToken(Parser, NULL, TRUE); if (ParseStatementMaybeRun(Parser, !Condition, TRUE) != ParseResultOk) ProgramFail(Parser, "statement expected"); } CheckTrailingSemicolon = FALSE; break; case TokenWhile: { struct ParseState PreConditional; enum RunMode PreMode = Parser->Mode; if (LexGetToken(Parser, NULL, TRUE) != TokenOpenBracket) ProgramFail(Parser, "'(' expected"); ParserCopyPos(&PreConditional, Parser); do { ParserCopyPos(Parser, &PreConditional); Condition = ExpressionParseInt(Parser); if (LexGetToken(Parser, NULL, TRUE) != TokenCloseBracket) ProgramFail(Parser, "')' expected"); if (ParseStatementMaybeRun(Parser, Condition, TRUE) != ParseResultOk) ProgramFail(Parser, "statement expected"); if (Parser->Mode == RunModeContinue) Parser->Mode = PreMode; } while (Parser->Mode == RunModeRun && Condition); if (Parser->Mode == RunModeBreak) Parser->Mode = PreMode; CheckTrailingSemicolon = FALSE; } break; case TokenDo: { struct ParseState PreStatement; enum RunMode PreMode = Parser->Mode; ParserCopyPos(&PreStatement, Parser); do { ParserCopyPos(Parser, &PreStatement); if (ParseStatement(Parser, TRUE) != ParseResultOk) ProgramFail(Parser, "statement expected"); if (Parser->Mode == RunModeContinue) Parser->Mode = PreMode; if (LexGetToken(Parser, NULL, TRUE) != TokenWhile) ProgramFail(Parser, "'while' expected"); if (LexGetToken(Parser, NULL, TRUE) != TokenOpenBracket) ProgramFail(Parser, "'(' expected"); Condition = ExpressionParseInt(Parser); if (LexGetToken(Parser, NULL, TRUE) != TokenCloseBracket) ProgramFail(Parser, "')' expected"); } while (Condition && Parser->Mode == RunModeRun); if (Parser->Mode == RunModeBreak) Parser->Mode = PreMode; } break; case TokenFor: ParseFor(Parser); CheckTrailingSemicolon = FALSE; break; case TokenSemicolon: CheckTrailingSemicolon = FALSE; break; case TokenIntType: case TokenShortType: case TokenCharType: case TokenLongType: case TokenFloatType: case TokenDoubleType: case TokenVoidType: case TokenStructType: case TokenUnionType: case TokenEnumType: case TokenSignedType: case TokenUnsignedType: case TokenStaticType: case TokenAutoType: case TokenRegisterType: case TokenExternType: *Parser = PreState; CheckTrailingSemicolon = ParseDeclaration(Parser, Token); break; case TokenHashDefine: ParseMacroDefinition(Parser); CheckTrailingSemicolon = FALSE; break; #ifndef NO_HASH_INCLUDE case TokenHashInclude: if (LexGetToken(Parser, &LexerValue, TRUE) != TokenStringConstant) ProgramFail(Parser, "\"filename.h\" expected"); IncludeFile(Parser->pc, (char *)LexerValue->Val->Pointer); CheckTrailingSemicolon = FALSE; break; #endif case TokenSwitch: if (LexGetToken(Parser, NULL, TRUE) != TokenOpenBracket) ProgramFail(Parser, "'(' expected"); Condition = ExpressionParseInt(Parser); if (LexGetToken(Parser, NULL, TRUE) != TokenCloseBracket) ProgramFail(Parser, "')' expected"); if (LexGetToken(Parser, NULL, FALSE) != TokenLeftBrace) ProgramFail(Parser, "'{' expected"); { /* new block so we can store parser state */ enum RunMode OldMode = Parser->Mode; int OldSearchLabel = Parser->SearchLabel; Parser->Mode = RunModeCaseSearch; Parser->SearchLabel = Condition; ParseBlock(Parser, TRUE, (OldMode != RunModeSkip) && (OldMode != RunModeReturn)); if (Parser->Mode != RunModeReturn) Parser->Mode = OldMode; Parser->SearchLabel = OldSearchLabel; } CheckTrailingSemicolon = FALSE; break; case TokenCase: if (Parser->Mode == RunModeCaseSearch) { Parser->Mode = RunModeRun; Condition = ExpressionParseInt(Parser); Parser->Mode = RunModeCaseSearch; } else Condition = ExpressionParseInt(Parser); if (LexGetToken(Parser, NULL, TRUE) != TokenColon) ProgramFail(Parser, "':' expected"); if (Parser->Mode == RunModeCaseSearch && Condition == Parser->SearchLabel) Parser->Mode = RunModeRun; CheckTrailingSemicolon = FALSE; break; case TokenDefault: if (LexGetToken(Parser, NULL, TRUE) != TokenColon) ProgramFail(Parser, "':' expected"); if (Parser->Mode == RunModeCaseSearch) Parser->Mode = RunModeRun; CheckTrailingSemicolon = FALSE; break; case TokenBreak: if (Parser->Mode == RunModeRun) Parser->Mode = RunModeBreak; break; case TokenContinue: if (Parser->Mode == RunModeRun) Parser->Mode = RunModeContinue; break; case TokenReturn: if (Parser->Mode == RunModeRun) { if (!Parser->pc->TopStackFrame || Parser->pc->TopStackFrame->ReturnValue->Typ->Base != TypeVoid) { if (!ExpressionParse(Parser, &CValue)) ProgramFail(Parser, "value required in return"); if (!Parser->pc->TopStackFrame) /* return from top-level program? */ PlatformExit(Parser->pc, ExpressionCoerceInteger(CValue)); else ExpressionAssign(Parser, Parser->pc->TopStackFrame->ReturnValue, CValue, TRUE, NULL, 0, FALSE); VariableStackPop(Parser, CValue); } else { if (ExpressionParse(Parser, &CValue)) ProgramFail(Parser, "value in return from a void function"); } Parser->Mode = RunModeReturn; } else ExpressionParse(Parser, &CValue); break; case TokenTypedef: ParseTypedef(Parser); break; case TokenGoto: if (LexGetToken(Parser, &LexerValue, TRUE) != TokenIdentifier) ProgramFail(Parser, "identifier expected"); if (Parser->Mode == RunModeRun) { /* start scanning for the goto label */ Parser->SearchGotoLabel = LexerValue->Val->Identifier; Parser->Mode = RunModeGoto; } break; case TokenDelete: { /* try it as a function or variable name to delete */ if (LexGetToken(Parser, &LexerValue, TRUE) != TokenIdentifier) ProgramFail(Parser, "identifier expected"); if (Parser->Mode == RunModeRun) { /* delete this variable or function */ CValue = TableDelete(Parser->pc, &Parser->pc->GlobalTable, LexerValue->Val->Identifier); if (CValue == NULL) ProgramFail(Parser, "'%s' is not defined", LexerValue->Val->Identifier); VariableFree(Parser->pc, CValue); } break; } default: *Parser = PreState; return ParseResultError; } if (CheckTrailingSemicolon) { if (LexGetToken(Parser, NULL, TRUE) != TokenSemicolon) ProgramFail(Parser, "';' expected"); } return ParseResultOk; }
/* intrinsic functions made available to the language */ void GenericPrintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs, struct OutputStream *Stream) { char *FPos; struct Value *NextArg = Param[0]; struct ValueType *FormatType; int ArgCount = 1; int LeftJustify = FALSE; int ZeroPad = FALSE; int FieldWidth = 0; char *Format = Param[0]->Val->Pointer; for (FPos = Format; *FPos != '\0'; FPos++) { if (*FPos == '%') { FPos++; if (*FPos == '-') { /* a leading '-' means left justify */ LeftJustify = TRUE; FPos++; } if (*FPos == '0') { /* a leading zero means zero pad a decimal number */ ZeroPad = TRUE; FPos++; } /* get any field width in the format */ while (isdigit((int)*FPos)) FieldWidth = FieldWidth * 10 + (*FPos++ - '0'); /* now check the format type */ switch (*FPos) { case 's': FormatType = CharPtrType; break; case 'd': case 'u': case 'x': case 'b': case 'c': FormatType = &IntType; break; #ifndef NO_FP case 'f': FormatType = &FPType; break; #endif case '%': PrintCh('%', Stream); FormatType = NULL; break; case '\0': FPos--; FormatType = NULL; break; default: PrintCh(*FPos, Stream); FormatType = NULL; break; } if (FormatType != NULL) { /* we have to format something */ if (ArgCount >= NumArgs) PrintStr("XXX", Stream); /* not enough parameters for format */ else { NextArg = (struct Value *)((char *)NextArg + MEM_ALIGN(sizeof(struct Value) + TypeStackSizeValue(NextArg))); if (NextArg->Typ != FormatType && !((FormatType == &IntType || *FPos == 'f') && IS_NUMERIC_COERCIBLE(NextArg)) && !(FormatType == CharPtrType && (NextArg->Typ->Base == TypePointer || (NextArg->Typ->Base == TypeArray && NextArg->Typ->FromType->Base == TypeChar) ) ) ) PrintStr("XXX", Stream); /* bad type for format */ else { switch (*FPos) { case 's': { char *Str; if (NextArg->Typ->Base == TypePointer) Str = NextArg->Val->Pointer; else Str = &NextArg->Val->ArrayMem[0]; if (Str == NULL) PrintStr("NULL", Stream); else PrintStr(Str, Stream); break; } case 'd': PrintInt(ExpressionCoerceInteger(NextArg), FieldWidth, ZeroPad, LeftJustify, Stream); break; case 'u': PrintUnsigned(ExpressionCoerceUnsignedInteger(NextArg), 10, FieldWidth, ZeroPad, LeftJustify, Stream); break; case 'x': PrintUnsigned(ExpressionCoerceUnsignedInteger(NextArg), 16, FieldWidth, ZeroPad, LeftJustify, Stream); break; case 'b': PrintUnsigned(ExpressionCoerceUnsignedInteger(NextArg), 2, FieldWidth, ZeroPad, LeftJustify, Stream); break; case 'c': PrintCh(ExpressionCoerceUnsignedInteger(NextArg), Stream); break; #ifndef NO_FP case 'f': PrintFP(ExpressionCoerceFP(NextArg), Stream); break; #endif } } } ArgCount++; } } else PrintCh(*FPos, Stream); } }
void GenericPrintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs, char * str) { const char *FPos; struct Value *NextArg = Param[0]; struct ValueType *FormatType; int ArgCount = 1; int LeftJustify = FALSE; int ZeroPad = FALSE; int FieldWidth = 0; const char *Format = Param[0]->Val->Pointer; int l; for (FPos = Format; *FPos != '\0'; FPos++) { if (*FPos == '%') { FPos++; if (*FPos == '-') { /* a leading '-' means left justify */ LeftJustify = TRUE; FPos++; } if (*FPos == '0') { /* a leading zero means zero pad a decimal number */ ZeroPad = TRUE; FPos++; } /* get any field width in the format */ while (isdigit((int)*FPos)) FieldWidth = FieldWidth * 10 + (*FPos++ - '0'); /* now check the format type */ switch (*FPos) { case 's': FormatType = CharPtrType; break; case 'd': case 'u': case 'x': case 'b': case 'c': FormatType = &IntType; break; case 'f': FormatType = &FPType; break; case '%': StrPutChar(str,'%');++str;FormatType = NULL; break; case '\0': FPos--; FormatType = NULL; break; default: StrPutChar(str,*FPos);++str; FormatType = NULL; break; } if (FormatType != NULL) { /* we have to format something */ if (ArgCount >= NumArgs) { l = StrPutStr(str,"XXX");str+=l; } else { // It won't compile if I don't add this. If you have an idea why, please tell me... actually this is defined in platform.h #define ALIGN_TYPE void * NextArg = (struct Value *)((char *)NextArg + MEM_ALIGN(sizeof(struct Value) + TypeStackSizeValue(NextArg))); if (NextArg->Typ != FormatType && !((FormatType == &IntType || *FPos == 'f') && IS_NUMERIC_COERCIBLE(NextArg)) && !(FormatType == CharPtrType && (NextArg->Typ->Base == TypePointer || (NextArg->Typ->Base == TypeArray && NextArg->Typ->FromType->Base == TypeChar) ) ) ) { l = StrPutStr(str,"XXX");str+=l; } else { switch (*FPos) { case 's': { char *Str; if (NextArg->Typ->Base == TypePointer) Str = NextArg->Val->Pointer; else Str = &NextArg->Val->ArrayMem[0]; if (Str == NULL) { l = StrPutStr(str,"NULL");str+=l; } else { l = StrPutStr(str,Str);str+=l; } break; } case 'd': l = sprintf(str,"%d",ExpressionCoerceInteger(NextArg));str+=l; break; case 'u': l = sprintf(str,"%u",ExpressionCoerceUnsignedInteger(NextArg));str+=l; break; case 'x': l = sprintf(str,"%x",ExpressionCoerceUnsignedInteger(NextArg));str+=l; break; case 'b': l = sprintf(str,"%b",ExpressionCoerceUnsignedInteger(NextArg));str+=l; break; case 'c': l = sprintf(str,"%c",ExpressionCoerceUnsignedInteger(NextArg));str+=l; break; case 'f': l = sprintf(str,"%f",ExpressionCoerceFP(NextArg));str+=l; break; } } } ArgCount++; } } else { StrPutChar(str,*FPos);++str; } } }