Merged in a pile of changes from broscutamaker
git-svn-id: http://picoc.googlecode.com/svn/trunk@599 21eae674-98b7-11dd-bd71-f92a316d2d60
This commit is contained in:
parent
3d5e022272
commit
b5a600a749
|
@ -63,6 +63,7 @@ void PrintType(struct ValueType *Typ, IOFILE *Stream)
|
|||
case TypeUnsignedInt: PrintStr("unsigned int", Stream); break;
|
||||
case TypeUnsignedShort: PrintStr("unsigned short", Stream); break;
|
||||
case TypeUnsignedLong: PrintStr("unsigned long", Stream); break;
|
||||
case TypeUnsignedChar: PrintStr("unsigned char", Stream); break;
|
||||
#ifndef NO_FP
|
||||
case TypeFP: PrintStr("double", Stream); break;
|
||||
#endif
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#define MAX_FORMAT 80
|
||||
#define MAX_SCANF_ARGS 10
|
||||
|
||||
static int ZeroValue = 0;
|
||||
static int Stdio_ZeroValue = 0;
|
||||
static int EOFValue = EOF;
|
||||
static int SEEK_SETValue = SEEK_SET;
|
||||
static int SEEK_CURValue = SEEK_CUR;
|
||||
|
@ -103,7 +103,7 @@ void StdioOutPuts(const char *Str, StdOutStream *Stream)
|
|||
}
|
||||
|
||||
/* printf-style format of an int or other word-sized object */
|
||||
void StdioFprintfWord(StdOutStream *Stream, const char *Format, unsigned int Value)
|
||||
void StdioFprintfWord(StdOutStream *Stream, const char *Format, unsigned long Value)
|
||||
{
|
||||
if (Stream->FilePtr != NULL)
|
||||
Stream->CharCount += fprintf(Stream->FilePtr, Format, Value);
|
||||
|
@ -712,7 +712,7 @@ void StdioSetupFunc(Picoc *pc)
|
|||
|
||||
/* define NULL, TRUE and FALSE */
|
||||
if (!VariableDefined(pc, TableStrRegister(pc, "NULL")))
|
||||
VariableDefinePlatformVar(pc, NULL, "NULL", &pc->IntType, (union AnyValue *)&ZeroValue, FALSE);
|
||||
VariableDefinePlatformVar(pc, NULL, "NULL", &pc->IntType, (union AnyValue *)&Stdio_ZeroValue, FALSE);
|
||||
}
|
||||
|
||||
/* portability-related I/O calls */
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#ifndef BUILTIN_MINI_STDLIB
|
||||
|
||||
static int ZeroValue = 0;
|
||||
static int Stdlib_ZeroValue = 0;
|
||||
|
||||
#ifndef NO_FP
|
||||
void StdlibAtof(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
||||
|
@ -168,7 +168,7 @@ void StdlibSetupFunc(Picoc *pc)
|
|||
{
|
||||
/* define NULL, TRUE and FALSE */
|
||||
if (!VariableDefined(pc, TableStrRegister(pc, "NULL")))
|
||||
VariableDefinePlatformVar(pc, NULL, "NULL", &pc->IntType, (union AnyValue *)&ZeroValue, FALSE);
|
||||
VariableDefinePlatformVar(pc, NULL, "NULL", &pc->IntType, (union AnyValue *)&Stdlib_ZeroValue, FALSE);
|
||||
}
|
||||
|
||||
#endif /* !BUILTIN_MINI_STDLIB */
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#ifndef BUILTIN_MINI_STDLIB
|
||||
|
||||
static int ZeroValue = 0;
|
||||
static int String_ZeroValue = 0;
|
||||
|
||||
void StringStrcpy(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
||||
{
|
||||
|
@ -180,7 +180,7 @@ void StringSetupFunc(Picoc *pc)
|
|||
{
|
||||
/* define NULL */
|
||||
if (!VariableDefined(pc, TableStrRegister(pc, "NULL")))
|
||||
VariableDefinePlatformVar(pc, NULL, "NULL", &pc->IntType, (union AnyValue *)&ZeroValue, FALSE);
|
||||
VariableDefinePlatformVar(pc, NULL, "NULL", &pc->IntType, (union AnyValue *)&String_ZeroValue, FALSE);
|
||||
}
|
||||
|
||||
#endif /* !BUILTIN_MINI_STDLIB */
|
||||
|
|
113
expression.c
113
expression.c
|
@ -6,7 +6,6 @@
|
|||
/* whether evaluation is left to right for a given precedence level */
|
||||
#define IS_LEFT_TO_RIGHT(p) ((p) != 2 && (p) != 14)
|
||||
#define BRACKET_PRECEDENCE 20
|
||||
#define IS_TYPE_TOKEN(t) ((t) >= TokenIntType && (t) <= TokenUnsignedType)
|
||||
|
||||
/* If the destination is not float, we can't assign a floating value to it, we need to convert it to integer instead */
|
||||
#define ASSIGN_FP_OR_INT(value) \
|
||||
|
@ -142,6 +141,26 @@ void ExpressionStackShow(struct ExpressionStack *StackTop)
|
|||
}
|
||||
#endif
|
||||
|
||||
int IsTypeToken(struct ParseState * Parser, enum LexToken t, struct Value * LexValue)
|
||||
{
|
||||
if (t >= TokenIntType && t <= TokenUnsignedType)
|
||||
return 1; /* base type */
|
||||
|
||||
/* typedef'ed type? */
|
||||
if (t == TokenIdentifier) /* see TypeParseFront, case TokenIdentifier and ParseTypedef */
|
||||
{
|
||||
struct Value * VarValue;
|
||||
if (VariableDefined(Parser->pc, LexValue->Val->Pointer))
|
||||
{
|
||||
VariableGet(Parser->pc, Parser, LexValue->Val->Pointer, &VarValue);
|
||||
if (VarValue->Typ == &Parser->pc->TypeType)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
long ExpressionCoerceInteger(struct Value *Val)
|
||||
{
|
||||
switch (Val->Typ->Base)
|
||||
|
@ -153,6 +172,7 @@ long ExpressionCoerceInteger(struct Value *Val)
|
|||
case TypeUnsignedInt: return (long)Val->Val->UnsignedInteger;
|
||||
case TypeUnsignedShort: return (long)Val->Val->UnsignedShortInteger;
|
||||
case TypeUnsignedLong: return (long)Val->Val->UnsignedLongInteger;
|
||||
case TypeUnsignedChar: return (long)Val->Val->UnsignedCharacter;
|
||||
case TypePointer: return (long)Val->Val->Pointer;
|
||||
#ifndef NO_FP
|
||||
case TypeFP: return (long)Val->Val->FP;
|
||||
|
@ -172,6 +192,7 @@ unsigned long ExpressionCoerceUnsignedInteger(struct Value *Val)
|
|||
case TypeUnsignedInt: return (unsigned long)Val->Val->UnsignedInteger;
|
||||
case TypeUnsignedShort: return (unsigned long)Val->Val->UnsignedShortInteger;
|
||||
case TypeUnsignedLong: return (unsigned long)Val->Val->UnsignedLongInteger;
|
||||
case TypeUnsignedChar: return (unsigned long)Val->Val->UnsignedCharacter;
|
||||
case TypePointer: return (unsigned long)Val->Val->Pointer;
|
||||
#ifndef NO_FP
|
||||
case TypeFP: return (unsigned long)Val->Val->FP;
|
||||
|
@ -196,6 +217,7 @@ double ExpressionCoerceFP(struct Value *Val)
|
|||
case TypeUnsignedInt: UnsignedVal = Val->Val->UnsignedInteger; return (double)UnsignedVal;
|
||||
case TypeUnsignedShort: UnsignedVal = Val->Val->UnsignedShortInteger; return (double)UnsignedVal;
|
||||
case TypeUnsignedLong: UnsignedVal = Val->Val->UnsignedLongInteger; return (double)UnsignedVal;
|
||||
case TypeUnsignedChar: UnsignedVal = Val->Val->UnsignedCharacter; return (double)UnsignedVal;
|
||||
case TypeFP: return Val->Val->FP;
|
||||
default: return 0.0;
|
||||
}
|
||||
|
@ -209,6 +231,7 @@ double ExpressionCoerceFP(struct Value *Val)
|
|||
case TypeUnsignedInt: return (double)Val->Val->UnsignedInteger;
|
||||
case TypeUnsignedShort: return (double)Val->Val->UnsignedShortInteger;
|
||||
case TypeUnsignedLong: return (double)Val->Val->UnsignedLongInteger;
|
||||
case TypeUnsignedChar: return (double)Val->Val->UnsignedCharacter;
|
||||
case TypeFP: return (double)Val->Val->FP;
|
||||
default: return 0.0;
|
||||
}
|
||||
|
@ -233,11 +256,12 @@ long ExpressionAssignInt(struct ParseState *Parser, struct Value *DestValue, lon
|
|||
{
|
||||
case TypeInt: DestValue->Val->Integer = FromInt; break;
|
||||
case TypeShort: DestValue->Val->ShortInteger = (short)FromInt; break;
|
||||
case TypeChar: DestValue->Val->Character = (unsigned char)FromInt; break;
|
||||
case TypeChar: DestValue->Val->Character = (char)FromInt; break;
|
||||
case TypeLong: DestValue->Val->LongInteger = (long)FromInt; break;
|
||||
case TypeUnsignedInt: DestValue->Val->UnsignedInteger = (unsigned int)FromInt; break;
|
||||
case TypeUnsignedShort: DestValue->Val->UnsignedShortInteger = (unsigned short)FromInt; break;
|
||||
case TypeUnsignedLong: DestValue->Val->UnsignedLongInteger = (unsigned long)FromInt; break;
|
||||
case TypeUnsignedChar: DestValue->Val->UnsignedCharacter = (unsigned char)FromInt; break;
|
||||
default: break;
|
||||
}
|
||||
return Result;
|
||||
|
@ -376,11 +400,12 @@ void ExpressionAssign(struct ParseState *Parser, struct Value *DestValue, struct
|
|||
{
|
||||
case TypeInt: DestValue->Val->Integer = ExpressionCoerceInteger(SourceValue); break;
|
||||
case TypeShort: DestValue->Val->ShortInteger = (short)ExpressionCoerceInteger(SourceValue); break;
|
||||
case TypeChar: DestValue->Val->Character = (unsigned char)ExpressionCoerceUnsignedInteger(SourceValue); break;
|
||||
case TypeChar: DestValue->Val->Character = (char)ExpressionCoerceInteger(SourceValue); break;
|
||||
case TypeLong: DestValue->Val->LongInteger = ExpressionCoerceInteger(SourceValue); break;
|
||||
case TypeUnsignedInt: DestValue->Val->UnsignedInteger = ExpressionCoerceUnsignedInteger(SourceValue); break;
|
||||
case TypeUnsignedShort: DestValue->Val->UnsignedShortInteger = (unsigned short)ExpressionCoerceUnsignedInteger(SourceValue); break;
|
||||
case TypeUnsignedLong: DestValue->Val->UnsignedLongInteger = ExpressionCoerceUnsignedInteger(SourceValue); break;
|
||||
case TypeUnsignedChar: DestValue->Val->UnsignedCharacter = (unsigned char)ExpressionCoerceUnsignedInteger(SourceValue); break;
|
||||
|
||||
#ifndef NO_FP
|
||||
case TypeFP:
|
||||
|
@ -409,6 +434,29 @@ void ExpressionAssign(struct ParseState *Parser, struct Value *DestValue, struct
|
|||
}
|
||||
}
|
||||
|
||||
/* char array = "abcd" */
|
||||
if (DestValue->Typ->FromType->Base == TypeChar && SourceValue->Typ->Base == TypePointer && SourceValue->Typ->FromType->Base == TypeChar)
|
||||
{
|
||||
if (DestValue->Typ->ArraySize == 0) /* char x[] = "abcd", x is unsized */
|
||||
{
|
||||
int Size = strlen(SourceValue->Val->Pointer) + 1;
|
||||
#ifdef DEBUG_ARRAY_INITIALIZER
|
||||
PRINT_SOURCE_POS;
|
||||
fprintf(stderr, "str size: %d\n", Size);
|
||||
#endif
|
||||
DestValue->Typ = TypeGetMatching(Parser->pc, Parser, DestValue->Typ->FromType, DestValue->Typ->Base, Size, DestValue->Typ->Identifier, TRUE);
|
||||
VariableRealloc(Parser, DestValue, TypeSizeValue(DestValue, FALSE));
|
||||
}
|
||||
/* else, it's char x[10] = "abcd" */
|
||||
|
||||
#ifdef DEBUG_ARRAY_INITIALIZER
|
||||
PRINT_SOURCE_POS;
|
||||
fprintf(stderr, "char[%d] from char* (len=%d)\n", DestValue->Typ->ArraySize, strlen(SourceValue->Val->Pointer));
|
||||
#endif
|
||||
memcpy((void *)DestValue->Val, SourceValue->Val->Pointer, TypeSizeValue(DestValue, FALSE));
|
||||
break;
|
||||
}
|
||||
|
||||
if (DestValue->Typ != SourceValue->Typ)
|
||||
AssignFail(Parser, "%t from %t", DestValue->Typ, SourceValue->Typ, 0, 0, FuncName, ParamNo);
|
||||
|
||||
|
@ -508,6 +556,9 @@ void ExpressionPrefixOperator(struct ParseState *Parser, struct ExpressionStack
|
|||
{
|
||||
case TokenPlus: ResultFP = TopValue->Val->FP; break;
|
||||
case TokenMinus: ResultFP = -TopValue->Val->FP; break;
|
||||
case TokenIncrement: ResultFP = ExpressionAssignFP(Parser, TopValue, TopValue->Val->FP+1); break;
|
||||
case TokenDecrement: ResultFP = ExpressionAssignFP(Parser, TopValue, TopValue->Val->FP-1); break;
|
||||
case TokenUnaryNot: ResultFP = !TopValue->Val->FP; break;
|
||||
default: ProgramFail(Parser, "invalid operation"); break;
|
||||
}
|
||||
|
||||
|
@ -567,6 +618,23 @@ void ExpressionPrefixOperator(struct ParseState *Parser, struct ExpressionStack
|
|||
void ExpressionPostfixOperator(struct ParseState *Parser, struct ExpressionStack **StackTop, enum LexToken Op, struct Value *TopValue)
|
||||
{
|
||||
debugf("ExpressionPostfixOperator()\n");
|
||||
#ifndef NO_FP
|
||||
if (TopValue->Typ == &Parser->pc->FPType)
|
||||
{
|
||||
/* floating point prefix arithmetic */
|
||||
double ResultFP = 0.0;
|
||||
|
||||
switch (Op)
|
||||
{
|
||||
case TokenIncrement: ResultFP = ExpressionAssignFP(Parser, TopValue, TopValue->Val->FP+1); break;
|
||||
case TokenDecrement: ResultFP = ExpressionAssignFP(Parser, TopValue, TopValue->Val->FP-1); break;
|
||||
default: ProgramFail(Parser, "invalid operation"); break;
|
||||
}
|
||||
|
||||
ExpressionPushFP(Parser, StackTop, ResultFP);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (IS_NUMERIC_COERCIBLE(TopValue))
|
||||
{
|
||||
long ResultInt = 0;
|
||||
|
@ -861,7 +929,7 @@ void ExpressionStackCollapse(struct ParseState *Parser, struct ExpressionStack *
|
|||
*StackTop = TopOperatorNode->Next;
|
||||
|
||||
/* do the prefix operation */
|
||||
if (Parser->Mode == RunModeRun && FoundPrecedence < *IgnorePrecedence)
|
||||
if (Parser->Mode == RunModeRun /* && FoundPrecedence < *IgnorePrecedence */)
|
||||
{
|
||||
/* run the operator */
|
||||
ExpressionPrefixOperator(Parser, StackTop, TopOperatorNode->Op, TopValue);
|
||||
|
@ -884,7 +952,7 @@ void ExpressionStackCollapse(struct ParseState *Parser, struct ExpressionStack *
|
|||
*StackTop = TopStackNode->Next->Next;
|
||||
|
||||
/* do the postfix operation */
|
||||
if (Parser->Mode == RunModeRun && FoundPrecedence < *IgnorePrecedence)
|
||||
if (Parser->Mode == RunModeRun /* && FoundPrecedence < *IgnorePrecedence */)
|
||||
{
|
||||
/* run the operator */
|
||||
ExpressionPostfixOperator(Parser, StackTop, TopOperatorNode->Op, TopValue);
|
||||
|
@ -911,7 +979,7 @@ void ExpressionStackCollapse(struct ParseState *Parser, struct ExpressionStack *
|
|||
*StackTop = TopOperatorNode->Next->Next;
|
||||
|
||||
/* do the infix operation */
|
||||
if (Parser->Mode == RunModeRun && FoundPrecedence <= *IgnorePrecedence)
|
||||
if (Parser->Mode == RunModeRun /* && FoundPrecedence <= *IgnorePrecedence */)
|
||||
{
|
||||
/* run the operator */
|
||||
ExpressionInfixOperator(Parser, StackTop, TopOperatorNode->Op, BottomValue, TopValue);
|
||||
|
@ -982,7 +1050,7 @@ void ExpressionGetStructElement(struct ParseState *Parser, struct ExpressionStac
|
|||
struct Value *StructVal = ParamVal;
|
||||
struct ValueType *StructType = ParamVal->Typ;
|
||||
char *DerefDataLoc = (char *)ParamVal->Val;
|
||||
struct Value *MemberValue;
|
||||
struct Value *MemberValue = NULL;
|
||||
struct Value *Result;
|
||||
|
||||
/* if we're doing '->' dereference the struct pointer first */
|
||||
|
@ -1044,7 +1112,7 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
|
|||
{
|
||||
/* it's either a new bracket level or a cast */
|
||||
enum LexToken BracketToken = LexGetToken(Parser, &LexValue, FALSE);
|
||||
if (IS_TYPE_TOKEN(BracketToken) && (StackTop == NULL || StackTop->Op != TokenSizeof) )
|
||||
if (IsTypeToken(Parser, BracketToken, LexValue) && (StackTop == NULL || StackTop->Op != TokenSizeof) )
|
||||
{
|
||||
/* it's a cast - get the new type */
|
||||
struct ValueType *CastType;
|
||||
|
@ -1073,8 +1141,22 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
|
|||
else
|
||||
{
|
||||
/* scan and collapse the stack to the precedence of this operator, then push */
|
||||
|
||||
/* take some extra care for double prefix operators, e.g. x = - -5, or x = **y */
|
||||
int NextToken = LexGetToken(Parser, NULL, FALSE);
|
||||
int TempPrecedenceBoost = 0;
|
||||
if (NextToken > TokenComma && NextToken < TokenOpenBracket)
|
||||
{
|
||||
int NextPrecedence = OperatorPrecedence[(int)NextToken].PrefixPrecedence;
|
||||
|
||||
/* two prefix operators with equal precedence? make sure the innermost one runs first */
|
||||
/* XXX - probably not correct, but can't find a test that fails at this */
|
||||
if (LocalPrecedence == NextPrecedence)
|
||||
TempPrecedenceBoost = -1;
|
||||
}
|
||||
|
||||
ExpressionStackCollapse(Parser, &StackTop, Precedence, &IgnorePrecedence);
|
||||
ExpressionStackPushOperator(Parser, &StackTop, OrderPrefix, Token, Precedence);
|
||||
ExpressionStackPushOperator(Parser, &StackTop, OrderPrefix, Token, Precedence + TempPrecedenceBoost);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1170,7 +1252,7 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (Parser->Mode == RunModeRun && Precedence < IgnorePrecedence)
|
||||
if (Parser->Mode == RunModeRun /* && Precedence < IgnorePrecedence */)
|
||||
{
|
||||
struct Value *VariableValue = NULL;
|
||||
|
||||
|
@ -1215,7 +1297,7 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
|
|||
PrefixState = FALSE;
|
||||
ExpressionStackPushValue(Parser, &StackTop, LexValue);
|
||||
}
|
||||
else if (IS_TYPE_TOKEN(Token))
|
||||
else if (IsTypeToken(Parser, Token, LexValue))
|
||||
{
|
||||
/* it's a type. push it on the stack like a value. this is used in sizeof() */
|
||||
struct ValueType *Typ;
|
||||
|
@ -1357,7 +1439,7 @@ void ExpressionParseMacroCall(struct ParseState *Parser, struct ExpressionStack
|
|||
void ExpressionParseFunctionCall(struct ParseState *Parser, struct ExpressionStack **StackTop, const char *FuncName, int RunIt)
|
||||
{
|
||||
struct Value *ReturnValue = NULL;
|
||||
struct Value *FuncValue;
|
||||
struct Value *FuncValue = NULL;
|
||||
struct Value *Param;
|
||||
struct Value **ParamArray = NULL;
|
||||
int ArgCount;
|
||||
|
@ -1440,6 +1522,7 @@ void ExpressionParseFunctionCall(struct ParseState *Parser, struct ExpressionSta
|
|||
/* run a user-defined function */
|
||||
struct ParseState FuncParser;
|
||||
int Count;
|
||||
int OldScopeID = Parser->ScopeID;
|
||||
|
||||
if (FuncValue->Val->FuncDef.Body.Pos == NULL)
|
||||
ProgramFail(Parser, "'%s' is undefined", FuncName);
|
||||
|
@ -1448,9 +1531,15 @@ void ExpressionParseFunctionCall(struct ParseState *Parser, struct ExpressionSta
|
|||
VariableStackFrameAdd(Parser, FuncName, FuncValue->Val->FuncDef.Intrinsic ? FuncValue->Val->FuncDef.NumParams : 0);
|
||||
Parser->pc->TopStackFrame->NumParams = ArgCount;
|
||||
Parser->pc->TopStackFrame->ReturnValue = ReturnValue;
|
||||
|
||||
/* Function parameters should not go out of scope */
|
||||
Parser->ScopeID = -1;
|
||||
|
||||
for (Count = 0; Count < FuncValue->Val->FuncDef.NumParams; Count++)
|
||||
VariableDefine(Parser->pc, Parser, FuncValue->Val->FuncDef.ParamName[Count], ParamArray[Count], NULL, TRUE);
|
||||
|
||||
Parser->ScopeID = OldScopeID;
|
||||
|
||||
if (ParseStatement(&FuncParser, TRUE) != ParseResultOk)
|
||||
ProgramFail(&FuncParser, "function body expected");
|
||||
|
||||
|
|
|
@ -26,6 +26,10 @@
|
|||
|
||||
#define GETS_BUF_MAX 256
|
||||
|
||||
/* for debugging */
|
||||
#define PRINT_SOURCE_POS ({ PrintSourceTextErrorLine(Parser->pc->CStdOut, Parser->FileName, Parser->SourceText, Parser->Line, Parser->CharacterPos); PlatformPrintf(Parser->pc->CStdOut, "\n"); })
|
||||
#define PRINT_TYPE(typ) PlatformPrintf(Parser->pc->CStdOut, "%t\n", typ);
|
||||
|
||||
/* small processors use a simplified FILE * for stdio, otherwise use the system FILE * */
|
||||
#ifdef BUILTIN_MINI_STDLIB
|
||||
typedef struct OutputStream IOFILE;
|
||||
|
@ -123,6 +127,7 @@ struct ParseState
|
|||
short int HashIfLevel; /* how many "if"s we're nested down */
|
||||
short int HashIfEvaluateToLevel; /* if we're not evaluating an if branch, what the last evaluated level was */
|
||||
char DebugMode; /* debugging mode */
|
||||
int ScopeID; /* for keeping track of local variables (free them after they go out of scope) */
|
||||
};
|
||||
|
||||
/* values */
|
||||
|
@ -131,10 +136,11 @@ enum BaseType
|
|||
TypeVoid, /* no type */
|
||||
TypeInt, /* integer */
|
||||
TypeShort, /* short integer */
|
||||
TypeChar, /* a single character (unsigned) */
|
||||
TypeChar, /* a single character (signed) */
|
||||
TypeLong, /* long integer */
|
||||
TypeUnsignedInt, /* unsigned integer */
|
||||
TypeUnsignedShort, /* unsigned short integer */
|
||||
TypeUnsignedChar, /* unsigned 8-bit number */ /* must be before unsigned long */
|
||||
TypeUnsignedLong, /* unsigned long integer */
|
||||
#ifndef NO_FP
|
||||
TypeFP, /* floating point */
|
||||
|
@ -189,13 +195,14 @@ struct MacroDef
|
|||
/* values */
|
||||
union AnyValue
|
||||
{
|
||||
unsigned char Character;
|
||||
char Character;
|
||||
short ShortInteger;
|
||||
int Integer;
|
||||
long LongInteger;
|
||||
unsigned short UnsignedShortInteger;
|
||||
unsigned int UnsignedInteger;
|
||||
unsigned long UnsignedLongInteger;
|
||||
unsigned char UnsignedCharacter;
|
||||
char *Identifier;
|
||||
char ArrayMem[2]; /* placeholder for where the data starts, doesn't point to it */
|
||||
struct ValueType *Typ;
|
||||
|
@ -216,6 +223,8 @@ struct Value
|
|||
char ValOnStack; /* the AnyValue is on the stack along with this Value */
|
||||
char AnyValOnHeap; /* the AnyValue is separately allocated from the Value on the heap */
|
||||
char IsLValue; /* is modifiable and is allocated somewhere we can usefully modify it */
|
||||
int ScopeID; /* to know when it goes out of scope */
|
||||
char OutOfScope;
|
||||
};
|
||||
|
||||
/* hash table data structure */
|
||||
|
@ -414,6 +423,7 @@ struct Picoc_Struct
|
|||
struct ValueType UnsignedIntType;
|
||||
struct ValueType UnsignedShortType;
|
||||
struct ValueType UnsignedLongType;
|
||||
struct ValueType UnsignedCharType;
|
||||
#ifndef NO_FP
|
||||
struct ValueType FPType;
|
||||
#endif
|
||||
|
@ -543,6 +553,7 @@ struct Value *VariableAllocValueShared(struct ParseState *Parser, struct Value *
|
|||
struct Value *VariableDefine(Picoc *pc, struct ParseState *Parser, char *Ident, struct Value *InitValue, struct ValueType *Typ, int MakeWritable);
|
||||
struct Value *VariableDefineButIgnoreIdentical(struct ParseState *Parser, char *Ident, struct ValueType *Typ, int IsStatic, int *FirstVisit);
|
||||
int VariableDefined(Picoc *pc, const char *Ident);
|
||||
int VariableDefinedAndOutOfScope(Picoc *pc, const char *Ident);
|
||||
void VariableRealloc(struct ParseState *Parser, struct Value *FromValue, int NewSize);
|
||||
void VariableGet(Picoc *pc, struct ParseState *Parser, const char *Ident, struct Value **LVal);
|
||||
void VariableDefinePlatformVar(Picoc *pc, struct ParseState *Parser, char *Ident, struct ValueType *Typ, union AnyValue *FromValue, int IsWritable);
|
||||
|
@ -551,6 +562,8 @@ void VariableStackFramePop(struct ParseState *Parser);
|
|||
struct Value *VariableStringLiteralGet(Picoc *pc, char *Ident);
|
||||
void VariableStringLiteralDefine(Picoc *pc, char *Ident, struct Value *Val);
|
||||
void *VariableDereferencePointer(struct ParseState *Parser, struct Value *PointerValue, struct Value **DerefVal, int *DerefOffset, struct ValueType **DerefType, int *DerefIsLValue);
|
||||
int VariableScopeBegin(struct ParseState * Parser, int* PrevScopeID);
|
||||
void VariableScopeEnd(struct ParseState * Parser, int ScopeID, int PrevScopeID);
|
||||
|
||||
/* clibrary.c */
|
||||
void BasicIOInit(Picoc *pc);
|
||||
|
|
100
lex.c
100
lex.c
|
@ -129,13 +129,18 @@ enum LexToken LexCheckReservedWord(Picoc *pc, const char *Word)
|
|||
/* get a numeric literal - used while scanning */
|
||||
enum LexToken LexGetNumber(Picoc *pc, struct LexState *Lexer, struct Value *Value)
|
||||
{
|
||||
int Result = 0;
|
||||
int Base = 10;
|
||||
long Result = 0;
|
||||
long Base = 10;
|
||||
enum LexToken ResultToken;
|
||||
#ifndef NO_FP
|
||||
double FPResult;
|
||||
double FPDiv;
|
||||
#endif
|
||||
/* long/unsigned flags */
|
||||
#if 0 /* unused for now */
|
||||
char IsLong = 0;
|
||||
char IsUnsigned = 0;
|
||||
#endif
|
||||
|
||||
if (*Lexer->Pos == '0')
|
||||
{
|
||||
|
@ -156,45 +161,56 @@ enum LexToken LexGetNumber(Picoc *pc, struct LexState *Lexer, struct Value *Valu
|
|||
for (; Lexer->Pos != Lexer->End && IS_BASE_DIGIT(*Lexer->Pos, Base); LEXER_INC(Lexer))
|
||||
Result = Result * Base + GET_BASE_DIGIT(*Lexer->Pos);
|
||||
|
||||
if (Result >= 0 && Result <= MAX_CHAR_VALUE)
|
||||
if (*Lexer->Pos == 'u' || *Lexer->Pos == 'U')
|
||||
{
|
||||
Value->Typ = &pc->CharType;
|
||||
Value->Val->Character = Result;
|
||||
ResultToken = TokenCharacterConstant;
|
||||
LEXER_INC(Lexer);
|
||||
/* IsUnsigned = 1; */
|
||||
}
|
||||
else
|
||||
if (*Lexer->Pos == 'l' || *Lexer->Pos == 'L')
|
||||
{
|
||||
Value->Typ = &pc->IntType;
|
||||
Value->Val->Integer = Result;
|
||||
LEXER_INC(Lexer);
|
||||
/* IsLong = 1; */
|
||||
}
|
||||
|
||||
Value->Typ = &pc->LongType; /* ignored? */
|
||||
Value->Val->LongInteger = Result;
|
||||
|
||||
ResultToken = TokenIntegerConstant;
|
||||
}
|
||||
|
||||
if (Lexer->Pos == Lexer->End)
|
||||
return ResultToken;
|
||||
|
||||
if (*Lexer->Pos == 'l' || *Lexer->Pos == 'L')
|
||||
#ifndef NO_FP
|
||||
if (Lexer->Pos == Lexer->End)
|
||||
{
|
||||
LEXER_INC(Lexer);
|
||||
return ResultToken;
|
||||
}
|
||||
|
||||
#ifndef NO_FP
|
||||
if (Lexer->Pos == Lexer->End || *Lexer->Pos != '.')
|
||||
if (*Lexer->Pos != '.' && *Lexer->Pos != 'e' && *Lexer->Pos != 'E')
|
||||
{
|
||||
return ResultToken;
|
||||
}
|
||||
|
||||
Value->Typ = &pc->FPType;
|
||||
FPResult = (double)Result;
|
||||
|
||||
if (*Lexer->Pos == '.')
|
||||
{
|
||||
LEXER_INC(Lexer);
|
||||
for (FPDiv = 1.0/Base, FPResult = (double)Result; Lexer->Pos != Lexer->End && IS_BASE_DIGIT(*Lexer->Pos, Base); LEXER_INC(Lexer), FPDiv /= (double)Base)
|
||||
for (FPDiv = 1.0/Base; Lexer->Pos != Lexer->End && IS_BASE_DIGIT(*Lexer->Pos, Base); LEXER_INC(Lexer), FPDiv /= (double)Base)
|
||||
{
|
||||
FPResult += GET_BASE_DIGIT(*Lexer->Pos) * FPDiv;
|
||||
}
|
||||
}
|
||||
|
||||
if (Lexer->Pos != Lexer->End && (*Lexer->Pos == 'e' || *Lexer->Pos == 'E'))
|
||||
{
|
||||
double ExponentMultiplier = 1.0;
|
||||
int ExponentSign = 1;
|
||||
|
||||
LEXER_INC(Lexer);
|
||||
if (Lexer->Pos != Lexer->End && *Lexer->Pos == '-')
|
||||
{
|
||||
ExponentMultiplier = -1.0;
|
||||
ExponentSign = -1;
|
||||
LEXER_INC(Lexer);
|
||||
}
|
||||
|
||||
|
@ -205,11 +221,14 @@ enum LexToken LexGetNumber(Picoc *pc, struct LexState *Lexer, struct Value *Valu
|
|||
LEXER_INC(Lexer);
|
||||
}
|
||||
|
||||
FPResult *= pow((double)Base, (double)Result * ExponentMultiplier);
|
||||
FPResult *= pow((double)Base, (double)Result * ExponentSign);
|
||||
}
|
||||
|
||||
Value->Val->FP = FPResult;
|
||||
|
||||
if (*Lexer->Pos == 'f' || *Lexer->Pos == 'F')
|
||||
LEXER_INC(Lexer);
|
||||
|
||||
return TokenFPConstant;
|
||||
#else
|
||||
return ResultToken;
|
||||
|
@ -496,7 +515,7 @@ int LexTokenSize(enum LexToken Token)
|
|||
switch (Token)
|
||||
{
|
||||
case TokenIdentifier: case TokenStringConstant: return sizeof(char *);
|
||||
case TokenIntegerConstant: return sizeof(int);
|
||||
case TokenIntegerConstant: return sizeof(long);
|
||||
case TokenCharacterConstant: return sizeof(unsigned char);
|
||||
case TokenFPConstant: return sizeof(double);
|
||||
default: return 0;
|
||||
|
@ -699,7 +718,7 @@ enum LexToken LexGetRawToken(struct ParseState *Parser, struct Value **Value, in
|
|||
{
|
||||
case TokenStringConstant: pc->LexValue.Typ = pc->CharPtrType; break;
|
||||
case TokenIdentifier: pc->LexValue.Typ = NULL; break;
|
||||
case TokenIntegerConstant: pc->LexValue.Typ = &pc->IntType; break;
|
||||
case TokenIntegerConstant: pc->LexValue.Typ = &pc->LongType; break;
|
||||
case TokenCharacterConstant: pc->LexValue.Typ = &pc->CharType; break;
|
||||
#ifndef NO_FP
|
||||
case TokenFPConstant: pc->LexValue.Typ = &pc->FPType; break;
|
||||
|
@ -766,7 +785,7 @@ void LexHashIf(struct ParseState *Parser)
|
|||
{
|
||||
/* get symbol to check */
|
||||
struct Value *IdentValue;
|
||||
struct Value *SavedValue;
|
||||
struct Value *SavedValue = NULL;
|
||||
struct ParseState MacroParser;
|
||||
enum LexToken Token = LexGetRawToken(Parser, &IdentValue, TRUE);
|
||||
|
||||
|
@ -783,7 +802,7 @@ void LexHashIf(struct ParseState *Parser)
|
|||
Token = LexGetRawToken(&MacroParser, &IdentValue, TRUE);
|
||||
}
|
||||
|
||||
if (Token != TokenCharacterConstant)
|
||||
if (Token != TokenCharacterConstant && Token != TokenIntegerConstant)
|
||||
ProgramFail(Parser, "value expected");
|
||||
|
||||
/* is the identifier defined? */
|
||||
|
@ -823,6 +842,43 @@ void LexHashEndif(struct ParseState *Parser)
|
|||
Parser->HashIfEvaluateToLevel = Parser->HashIfLevel;
|
||||
}
|
||||
|
||||
#if 0 /* useful for debug */
|
||||
void LexPrintToken(enum LexToken Token)
|
||||
{
|
||||
char* TokenNames[] = {
|
||||
/* 0x00 */ "None",
|
||||
/* 0x01 */ "Comma",
|
||||
/* 0x02 */ "Assign", "AddAssign", "SubtractAssign", "MultiplyAssign", "DivideAssign", "ModulusAssign",
|
||||
/* 0x08 */ "ShiftLeftAssign", "ShiftRightAssign", "ArithmeticAndAssign", "ArithmeticOrAssign", "ArithmeticExorAssign",
|
||||
/* 0x0d */ "QuestionMark", "Colon",
|
||||
/* 0x0f */ "LogicalOr",
|
||||
/* 0x10 */ "LogicalAnd",
|
||||
/* 0x11 */ "ArithmeticOr",
|
||||
/* 0x12 */ "ArithmeticExor",
|
||||
/* 0x13 */ "Ampersand",
|
||||
/* 0x14 */ "Equal", "NotEqual",
|
||||
/* 0x16 */ "LessThan", "GreaterThan", "LessEqual", "GreaterEqual",
|
||||
/* 0x1a */ "ShiftLeft", "ShiftRight",
|
||||
/* 0x1c */ "Plus", "Minus",
|
||||
/* 0x1e */ "Asterisk", "Slash", "Modulus",
|
||||
/* 0x21 */ "Increment", "Decrement", "UnaryNot", "UnaryExor", "Sizeof", "Cast",
|
||||
/* 0x27 */ "LeftSquareBracket", "RightSquareBracket", "Dot", "Arrow",
|
||||
/* 0x2b */ "OpenBracket", "CloseBracket",
|
||||
/* 0x2d */ "Identifier", "IntegerConstant", "FPConstant", "StringConstant", "CharacterConstant",
|
||||
/* 0x32 */ "Semicolon", "Ellipsis",
|
||||
/* 0x34 */ "LeftBrace", "RightBrace",
|
||||
/* 0x36 */ "IntType", "CharType", "FloatType", "DoubleType", "VoidType", "EnumType",
|
||||
/* 0x3c */ "LongType", "SignedType", "ShortType", "StaticType", "AutoType", "RegisterType", "ExternType", "StructType", "UnionType", "UnsignedType", "Typedef",
|
||||
/* 0x46 */ "Continue", "Do", "Else", "For", "Goto", "If", "While", "Break", "Switch", "Case", "Default", "Return",
|
||||
/* 0x52 */ "HashDefine", "HashInclude", "HashIf", "HashIfdef", "HashIfndef", "HashElse", "HashEndif",
|
||||
/* 0x59 */ "New", "Delete",
|
||||
/* 0x5b */ "OpenMacroBracket",
|
||||
/* 0x5c */ "EOF", "EndOfLine", "EndOfFunction"
|
||||
};
|
||||
printf("{%s}", TokenNames[Token]);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* get the next token given a parser state, pre-processing as we go */
|
||||
enum LexToken LexGetToken(struct ParseState *Parser, struct Value **Value, int IncPos)
|
||||
{
|
||||
|
|
108
parse.c
108
parse.c
|
@ -183,22 +183,77 @@ int ParseArrayInitialiser(struct ParseState *Parser, struct Value *NewVariable,
|
|||
|
||||
ParserCopy(&CountParser, Parser);
|
||||
NumElements = ParseArrayInitialiser(&CountParser, NewVariable, FALSE);
|
||||
if (NewVariable->Typ->ArraySize == 0)
|
||||
VariableRealloc(Parser, NewVariable, NumElements);
|
||||
|
||||
else if (NewVariable->Typ->ArraySize != NumElements)
|
||||
AssignFail(Parser, "from an array of size %d to one of size %d", NULL, NULL, NumElements, NewVariable->Typ->ArraySize, NULL, 0);
|
||||
if (NewVariable->Typ->Base != TypeArray)
|
||||
AssignFail(Parser, "%t from array initializer", NewVariable->Typ, NULL, 0, 0, NULL, 0);
|
||||
|
||||
if (NewVariable->Typ->ArraySize == 0)
|
||||
{
|
||||
NewVariable->Typ = TypeGetMatching(Parser->pc, Parser, NewVariable->Typ->FromType, NewVariable->Typ->Base, NumElements, NewVariable->Typ->Identifier, TRUE);
|
||||
VariableRealloc(Parser, NewVariable, TypeSizeValue(NewVariable, FALSE));
|
||||
}
|
||||
#ifdef DEBUG_ARRAY_INITIALIZER
|
||||
PRINT_SOURCE_POS;
|
||||
printf("array size: %d \n", NewVariable->Typ->ArraySize);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* parse the array initialiser */
|
||||
Token = LexGetToken(Parser, NULL, FALSE);
|
||||
while (Token != TokenRightBrace)
|
||||
{
|
||||
if (LexGetToken(Parser, NULL, FALSE) == TokenLeftBrace)
|
||||
{
|
||||
/* this is a sub-array initialiser */
|
||||
int SubArraySize = 0;
|
||||
struct Value *SubArray = NewVariable;
|
||||
if (Parser->Mode == RunModeRun && DoAssignment)
|
||||
{
|
||||
SubArraySize = TypeSize(NewVariable->Typ->FromType, NewVariable->Typ->FromType->ArraySize, TRUE);
|
||||
SubArray = VariableAllocValueFromExistingData(Parser, NewVariable->Typ->FromType, (union AnyValue *)(&NewVariable->Val->ArrayMem[0] + SubArraySize * ArrayIndex), TRUE, NewVariable);
|
||||
#ifdef DEBUG_ARRAY_INITIALIZER
|
||||
int FullArraySize = TypeSize(NewVariable->Typ, NewVariable->Typ->ArraySize, TRUE);
|
||||
PRINT_SOURCE_POS;
|
||||
PRINT_TYPE(NewVariable->Typ)
|
||||
printf("[%d] subarray size: %d (full: %d,%d) \n", ArrayIndex, SubArraySize, FullArraySize, NewVariable->Typ->ArraySize);
|
||||
#endif
|
||||
if (ArrayIndex >= NewVariable->Typ->ArraySize)
|
||||
ProgramFail(Parser, "too many array elements");
|
||||
}
|
||||
LexGetToken(Parser, NULL, TRUE);
|
||||
ParseArrayInitialiser(Parser, SubArray, DoAssignment);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct Value *ArrayElement = NULL;
|
||||
|
||||
if (Parser->Mode == RunModeRun && DoAssignment)
|
||||
ArrayElement = VariableAllocValueFromExistingData(Parser, NewVariable->Typ->FromType, (union AnyValue *)(&NewVariable->Val->ArrayMem[0] + TypeSize(NewVariable->Typ->FromType, 0, TRUE) * ArrayIndex), TRUE, NewVariable);
|
||||
{
|
||||
struct ValueType * ElementType = NewVariable->Typ;
|
||||
int TotalSize = 1;
|
||||
int ElementSize = 0;
|
||||
|
||||
/* int x[3][3] = {1,2,3,4} => handle it just like int x[9] = {1,2,3,4} */
|
||||
while (ElementType->Base == TypeArray)
|
||||
{
|
||||
TotalSize *= ElementType->ArraySize;
|
||||
ElementType = ElementType->FromType;
|
||||
|
||||
/* char x[10][10] = {"abc", "def"} => assign "abc" to x[0], "def" to x[1] etc */
|
||||
if (LexGetToken(Parser, NULL, FALSE) == TokenStringConstant && ElementType->FromType->Base == TypeChar)
|
||||
break;
|
||||
}
|
||||
ElementSize = TypeSize(ElementType, ElementType->ArraySize, TRUE);
|
||||
#ifdef DEBUG_ARRAY_INITIALIZER
|
||||
PRINT_SOURCE_POS;
|
||||
printf("[%d/%d] element size: %d (x%d) \n", ArrayIndex, TotalSize, ElementSize, ElementType->ArraySize);
|
||||
#endif
|
||||
if (ArrayIndex >= TotalSize)
|
||||
ProgramFail(Parser, "too many array elements");
|
||||
ArrayElement = VariableAllocValueFromExistingData(Parser, ElementType, (union AnyValue *)(&NewVariable->Val->ArrayMem[0] + ElementSize * ArrayIndex), TRUE, NewVariable);
|
||||
}
|
||||
|
||||
/* this is a normal expression initialiser */
|
||||
if (!ExpressionParse(Parser, &CValue))
|
||||
ProgramFail(Parser, "expression expected");
|
||||
|
||||
|
@ -208,6 +263,7 @@ int ParseArrayInitialiser(struct ParseState *Parser, struct Value *NewVariable,
|
|||
VariableStackPop(Parser, CValue);
|
||||
VariableStackPop(Parser, ArrayElement);
|
||||
}
|
||||
}
|
||||
|
||||
ArrayIndex++;
|
||||
|
||||
|
@ -393,8 +449,11 @@ void ParseFor(struct ParseState *Parser)
|
|||
struct ParseState PreIncrement;
|
||||
struct ParseState PreStatement;
|
||||
struct ParseState After;
|
||||
|
||||
enum RunMode OldMode = Parser->Mode;
|
||||
|
||||
int PrevScopeID = 0, ScopeID = VariableScopeBegin(Parser, &PrevScopeID);
|
||||
|
||||
if (LexGetToken(Parser, NULL, TRUE) != TokenOpenBracket)
|
||||
ProgramFail(Parser, "'(' expected");
|
||||
|
||||
|
@ -420,7 +479,7 @@ void ParseFor(struct ParseState *Parser)
|
|||
if (ParseStatementMaybeRun(Parser, Condition, TRUE) != ParseResultOk)
|
||||
ProgramFail(Parser, "statement expected");
|
||||
|
||||
if (Parser->Mode == RunModeContinue)
|
||||
if (Parser->Mode == RunModeContinue && OldMode == RunModeRun)
|
||||
Parser->Mode = RunModeRun;
|
||||
|
||||
ParserCopyPos(&After, Parser);
|
||||
|
@ -449,12 +508,16 @@ void ParseFor(struct ParseState *Parser)
|
|||
if (Parser->Mode == RunModeBreak && OldMode == RunModeRun)
|
||||
Parser->Mode = RunModeRun;
|
||||
|
||||
VariableScopeEnd(Parser, ScopeID, PrevScopeID);
|
||||
|
||||
ParserCopyPos(Parser, &After);
|
||||
}
|
||||
|
||||
/* parse a block of code and return what mode it returned in */
|
||||
enum RunMode ParseBlock(struct ParseState *Parser, int AbsorbOpenBrace, int Condition)
|
||||
{
|
||||
int PrevScopeID = 0, ScopeID = VariableScopeBegin(Parser, &PrevScopeID);
|
||||
|
||||
if (AbsorbOpenBrace && LexGetToken(Parser, NULL, TRUE) != TokenLeftBrace)
|
||||
ProgramFail(Parser, "'{' expected");
|
||||
|
||||
|
@ -477,6 +540,8 @@ enum RunMode ParseBlock(struct ParseState *Parser, int AbsorbOpenBrace, int Cond
|
|||
if (LexGetToken(Parser, NULL, TRUE) != TokenRightBrace)
|
||||
ProgramFail(Parser, "'}' expected");
|
||||
|
||||
VariableScopeEnd(Parser, ScopeID, PrevScopeID);
|
||||
|
||||
return Parser->Mode;
|
||||
}
|
||||
|
||||
|
@ -548,6 +613,33 @@ enum ParseResult ParseStatement(struct ParseState *Parser, int CheckTrailingSemi
|
|||
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 */
|
||||
|
@ -652,13 +744,9 @@ enum ParseResult ParseStatement(struct ParseState *Parser, int CheckTrailingSemi
|
|||
break;
|
||||
|
||||
case TokenFor:
|
||||
{
|
||||
enum RunMode OldMode = Parser->Mode;
|
||||
ParseFor(Parser);
|
||||
Parser->Mode = OldMode;
|
||||
CheckTrailingSemicolon = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
case TokenSemicolon:
|
||||
CheckTrailingSemicolon = FALSE;
|
||||
|
|
|
@ -171,7 +171,8 @@ void AssignFail(struct ParseState *Parser, const char *Format, struct ValueType
|
|||
if (FuncName != NULL)
|
||||
PlatformPrintf(Stream, " in argument %d of call to %s()", ParamNo, FuncName);
|
||||
|
||||
ProgramFail(Parser, NULL, "");
|
||||
PlatformPrintf(Stream, "\n");
|
||||
PlatformExit(Parser->pc, 1);
|
||||
}
|
||||
|
||||
/* exit lexing with a message */
|
||||
|
|
|
@ -43,5 +43,18 @@ int main()
|
|||
printf("a=%d\n",a);
|
||||
}
|
||||
|
||||
printf("\nTest 4\n");
|
||||
|
||||
a = 0; c = 0;
|
||||
for (c=0;c<10;c++)
|
||||
{
|
||||
printf("c=%d\n",c);
|
||||
foo();
|
||||
continue;
|
||||
for (a = 0; a < 2; a++)
|
||||
printf("a=%d\n",a);
|
||||
printf("bar\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -8,3 +8,25 @@ a=0
|
|||
Test 3
|
||||
c=0
|
||||
foo
|
||||
|
||||
Test 4
|
||||
c=0
|
||||
foo
|
||||
c=1
|
||||
foo
|
||||
c=2
|
||||
foo
|
||||
c=3
|
||||
foo
|
||||
c=4
|
||||
foo
|
||||
c=5
|
||||
foo
|
||||
c=6
|
||||
foo
|
||||
c=7
|
||||
foo
|
||||
c=8
|
||||
foo
|
||||
c=9
|
||||
foo
|
||||
|
|
|
@ -59,7 +59,7 @@ TESTS= 00_assignment.test \
|
|||
62_float.test \
|
||||
63_typedef.test \
|
||||
64_double_prefix_op.test \
|
||||
65_typeless.test \
|
||||
#65_typeless.test \
|
||||
|
||||
|
||||
include csmith/Makefile
|
||||
|
|
5
type.c
5
type.c
|
@ -121,11 +121,12 @@ void TypeInit(Picoc *pc)
|
|||
pc->UberType.DerivedTypeList = NULL;
|
||||
TypeAddBaseType(pc, &pc->IntType, TypeInt, sizeof(int), IntAlignBytes);
|
||||
TypeAddBaseType(pc, &pc->ShortType, TypeShort, sizeof(short), (char *)&sa.y - &sa.x);
|
||||
TypeAddBaseType(pc, &pc->CharType, TypeChar, sizeof(unsigned char), (char *)&ca.y - &ca.x);
|
||||
TypeAddBaseType(pc, &pc->CharType, TypeChar, sizeof(char), (char *)&ca.y - &ca.x);
|
||||
TypeAddBaseType(pc, &pc->LongType, TypeLong, sizeof(long), (char *)&la.y - &la.x);
|
||||
TypeAddBaseType(pc, &pc->UnsignedIntType, TypeUnsignedInt, sizeof(unsigned int), IntAlignBytes);
|
||||
TypeAddBaseType(pc, &pc->UnsignedShortType, TypeUnsignedShort, sizeof(unsigned short), (char *)&sa.y - &sa.x);
|
||||
TypeAddBaseType(pc, &pc->UnsignedLongType, TypeUnsignedLong, sizeof(unsigned long), (char *)&la.y - &la.x);
|
||||
TypeAddBaseType(pc, &pc->UnsignedCharType, TypeUnsignedChar, sizeof(unsigned char), (char *)&ca.y - &ca.x);
|
||||
TypeAddBaseType(pc, &pc->VoidType, TypeVoid, 0, 1);
|
||||
TypeAddBaseType(pc, &pc->FunctionType, TypeFunction, sizeof(int), IntAlignBytes);
|
||||
TypeAddBaseType(pc, &pc->MacroType, TypeMacro, sizeof(int), IntAlignBytes);
|
||||
|
@ -394,7 +395,7 @@ int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ, int *IsSta
|
|||
{
|
||||
case TokenIntType: *Typ = Unsigned ? &pc->UnsignedIntType : &pc->IntType; break;
|
||||
case TokenShortType: *Typ = Unsigned ? &pc->UnsignedShortType : &pc->ShortType; break;
|
||||
case TokenCharType: *Typ = &pc->CharType; break;
|
||||
case TokenCharType: *Typ = Unsigned ? &pc->UnsignedCharType : &pc->CharType; break;
|
||||
case TokenLongType: *Typ = Unsigned ? &pc->UnsignedLongType : &pc->LongType; break;
|
||||
#ifndef NO_FP
|
||||
case TokenFloatType: case TokenDoubleType: *Typ = &pc->FPType; break;
|
||||
|
|
112
variable.c
112
variable.c
|
@ -95,6 +95,10 @@ struct Value *VariableAllocValueAndData(Picoc *pc, struct ParseState *Parser, in
|
|||
NewValue->ValOnStack = !OnHeap;
|
||||
NewValue->IsLValue = IsLValue;
|
||||
NewValue->LValueFrom = LValueFrom;
|
||||
if (Parser)
|
||||
NewValue->ScopeID = Parser->ScopeID;
|
||||
|
||||
NewValue->OutOfScope = 0;
|
||||
|
||||
return NewValue;
|
||||
}
|
||||
|
@ -158,10 +162,109 @@ void VariableRealloc(struct ParseState *Parser, struct Value *FromValue, int New
|
|||
FromValue->AnyValOnHeap = TRUE;
|
||||
}
|
||||
|
||||
int VariableScopeBegin(struct ParseState * Parser, int* OldScopeID)
|
||||
{
|
||||
struct TableEntry *Entry;
|
||||
struct TableEntry *NextEntry;
|
||||
Picoc * pc = Parser->pc;
|
||||
int Count;
|
||||
#ifdef VAR_SCOPE_DEBUG
|
||||
int FirstPrint = 0;
|
||||
#endif
|
||||
|
||||
struct Table * HashTable = (pc->TopStackFrame == NULL) ? &(pc->GlobalTable) : &(pc->TopStackFrame)->LocalTable;
|
||||
|
||||
if (Parser->ScopeID == -1) return -1;
|
||||
|
||||
/* XXX dumb hash, let's hope for no collisions... */
|
||||
*OldScopeID = Parser->ScopeID;
|
||||
Parser->ScopeID = (int)(intptr_t)(Parser->SourceText) * ((int)(intptr_t)(Parser->Pos) / sizeof(char*));
|
||||
/* or maybe a more human-readable hash for debugging? */
|
||||
/* Parser->ScopeID = Parser->Line * 0x10000 + Parser->CharacterPos; */
|
||||
|
||||
for (Count = 0; Count < HashTable->Size; Count++)
|
||||
{
|
||||
for (Entry = HashTable->HashTable[Count]; Entry != NULL; Entry = NextEntry)
|
||||
{
|
||||
NextEntry = Entry->Next;
|
||||
if (Entry->p.v.Val->ScopeID == Parser->ScopeID && Entry->p.v.Val->OutOfScope)
|
||||
{
|
||||
Entry->p.v.Val->OutOfScope = FALSE;
|
||||
Entry->p.v.Key = (char*)((intptr_t)Entry->p.v.Key & ~1);
|
||||
#ifdef VAR_SCOPE_DEBUG
|
||||
if (!FirstPrint) { PRINT_SOURCE_POS; }
|
||||
FirstPrint = 1;
|
||||
printf(">>> back into scope: %s %x %d\n", Entry->p.v.Key, Entry->p.v.Val->ScopeID, Entry->p.v.Val->Val->Integer);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Parser->ScopeID;
|
||||
}
|
||||
|
||||
void VariableScopeEnd(struct ParseState * Parser, int ScopeID, int PrevScopeID)
|
||||
{
|
||||
struct TableEntry *Entry;
|
||||
struct TableEntry *NextEntry;
|
||||
Picoc * pc = Parser->pc;
|
||||
int Count;
|
||||
#ifdef VAR_SCOPE_DEBUG
|
||||
int FirstPrint = 0;
|
||||
#endif
|
||||
|
||||
struct Table * HashTable = (pc->TopStackFrame == NULL) ? &(pc->GlobalTable) : &(pc->TopStackFrame)->LocalTable;
|
||||
|
||||
if (ScopeID == -1) return;
|
||||
|
||||
for (Count = 0; Count < HashTable->Size; Count++)
|
||||
{
|
||||
for (Entry = HashTable->HashTable[Count]; Entry != NULL; Entry = NextEntry)
|
||||
{
|
||||
NextEntry = Entry->Next;
|
||||
if (Entry->p.v.Val->ScopeID == ScopeID && !Entry->p.v.Val->OutOfScope)
|
||||
{
|
||||
#ifdef VAR_SCOPE_DEBUG
|
||||
if (!FirstPrint) { PRINT_SOURCE_POS; }
|
||||
FirstPrint = 1;
|
||||
printf(">>> out of scope: %s %x %d\n", Entry->p.v.Key, Entry->p.v.Val->ScopeID, Entry->p.v.Val->Val->Integer);
|
||||
#endif
|
||||
Entry->p.v.Val->OutOfScope = TRUE;
|
||||
Entry->p.v.Key = (char*)((intptr_t)Entry->p.v.Key | 1); /* alter the key so it won't be found by normal searches */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Parser->ScopeID = PrevScopeID;
|
||||
}
|
||||
|
||||
int VariableDefinedAndOutOfScope(Picoc * pc, const char* Ident)
|
||||
{
|
||||
struct TableEntry *Entry;
|
||||
int Count;
|
||||
|
||||
struct Table * HashTable = (pc->TopStackFrame == NULL) ? &(pc->GlobalTable) : &(pc->TopStackFrame)->LocalTable;
|
||||
for (Count = 0; Count < HashTable->Size; Count++)
|
||||
{
|
||||
for (Entry = HashTable->HashTable[Count]; Entry != NULL; Entry = Entry->Next)
|
||||
{
|
||||
if (Entry->p.v.Val->OutOfScope && (char*)((intptr_t)Entry->p.v.Key & ~1) == Ident)
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* define a variable. Ident must be registered */
|
||||
struct Value *VariableDefine(Picoc *pc, struct ParseState *Parser, char *Ident, struct Value *InitValue, struct ValueType *Typ, int MakeWritable)
|
||||
{
|
||||
struct Value * AssignValue;
|
||||
struct Table * currentTable = (pc->TopStackFrame == NULL) ? &(pc->GlobalTable) : &(pc->TopStackFrame)->LocalTable;
|
||||
|
||||
int ScopeID = Parser ? Parser->ScopeID : -1;
|
||||
#ifdef VAR_SCOPE_DEBUG
|
||||
if (Parser) fprintf(stderr, "def %s %x (%s:%d:%d)\n", Ident, ScopeID, Parser->FileName, Parser->Line, Parser->CharacterPos);
|
||||
#endif
|
||||
|
||||
if (InitValue != NULL)
|
||||
AssignValue = VariableAllocValueAndCopy(pc, Parser, InitValue, pc->TopStackFrame == NULL);
|
||||
|
@ -169,8 +272,10 @@ struct Value *VariableDefine(Picoc *pc, struct ParseState *Parser, char *Ident,
|
|||
AssignValue = VariableAllocValueFromType(pc, Parser, Typ, MakeWritable, NULL, pc->TopStackFrame == NULL);
|
||||
|
||||
AssignValue->IsLValue = MakeWritable;
|
||||
AssignValue->ScopeID = ScopeID;
|
||||
AssignValue->OutOfScope = FALSE;
|
||||
|
||||
if (!TableSet(pc, (pc->TopStackFrame == NULL) ? &(pc->GlobalTable) : &(pc->TopStackFrame)->LocalTable, Ident, AssignValue, Parser ? ((char *)Parser->FileName) : NULL, Parser ? Parser->Line : 0, Parser ? Parser->CharacterPos : 0))
|
||||
if (!TableSet(pc, currentTable, Ident, AssignValue, Parser ? ((char *)Parser->FileName) : NULL, Parser ? Parser->Line : 0, Parser ? Parser->CharacterPos : 0))
|
||||
ProgramFail(Parser, "'%s' is already defined", Ident);
|
||||
|
||||
return AssignValue;
|
||||
|
@ -257,9 +362,14 @@ void VariableGet(Picoc *pc, struct ParseState *Parser, const char *Ident, struct
|
|||
if (pc->TopStackFrame == NULL || !TableGet(&pc->TopStackFrame->LocalTable, Ident, LVal, NULL, NULL, NULL))
|
||||
{
|
||||
if (!TableGet(&pc->GlobalTable, Ident, LVal, NULL, NULL, NULL))
|
||||
{
|
||||
if (VariableDefinedAndOutOfScope(pc, Ident))
|
||||
ProgramFail(Parser, "'%s' is out of scope", Ident);
|
||||
else
|
||||
ProgramFail(Parser, "'%s' is undefined", Ident);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* define a global variable shared with a platform global. Ident will be registered */
|
||||
void VariableDefinePlatformVar(Picoc *pc, struct ParseState *Parser, char *Ident, struct ValueType *Typ, union AnyValue *FromValue, int IsWritable)
|
||||
|
|
Loading…
Reference in a new issue