diff --git a/clibrary.c b/clibrary.c index 8d0fd60..88a073e 100644 --- a/clibrary.c +++ b/clibrary.c @@ -41,7 +41,7 @@ void LibraryAdd(struct Table *GlobalTable, const char *LibraryName, struct Libra { Tokens = LexAnalyse(IntrinsicName, FuncList[Count].Prototype, strlen((char *)FuncList[Count].Prototype), NULL); LexInitParser(&Parser, FuncList[Count].Prototype, Tokens, IntrinsicName, TRUE); - TypeParse(&Parser, &ReturnType, &Identifier); + TypeParse(&Parser, &ReturnType, &Identifier, NULL); NewValue = ParseFunctionDefinition(&Parser, ReturnType, Identifier); NewValue->Val->FuncDef.Intrinsic = FuncList[Count].Func; HeapFreeMem(Tokens); diff --git a/expression.c b/expression.c index 85dc5b3..bff30a2 100644 --- a/expression.c +++ b/expression.c @@ -966,7 +966,7 @@ void ExpressionGetStructElement(struct ParseState *Parser, struct ExpressionStac if (StructType->Base != TypeStruct && StructType->Base != TypeUnion) ProgramFail(Parser, "can't use '%s' on something that's not a struct or union %s : it's a %t", (Token == TokenDot) ? "." : "->", (Token == TokenArrow) ? "pointer" : "", ParamVal->Typ); - if (!TableGet(StructType->Members, Ident->Val->Identifier, &MemberValue, NULL, NULL)) + if (!TableGet(StructType->Members, Ident->Val->Identifier, &MemberValue, NULL, NULL, NULL)) ProgramFail(Parser, "doesn't have a member called '%s'", Ident->Val->Identifier); /* pop the value - assume it'll still be there until we're done */ @@ -1025,7 +1025,7 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result) char *CastIdentifier; struct Value *CastTypeValue; - TypeParse(Parser, &CastType, &CastIdentifier); + TypeParse(Parser, &CastType, &CastIdentifier, NULL); if (LexGetToken(Parser, &LexValue, TRUE) != TokenCloseBracket) ProgramFail(Parser, "brackets not closed"); @@ -1201,7 +1201,7 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result) PrefixState = FALSE; ParserCopy(Parser, &PreState); - TypeParse(Parser, &Typ, &Identifier); + TypeParse(Parser, &Typ, &Identifier, NULL); TypeValue = VariableAllocValueFromType(Parser, &TypeType, FALSE, NULL, FALSE); TypeValue->Val->Typ = Typ; ExpressionStackPushValueNode(Parser, &StackTop, TypeValue); @@ -1314,7 +1314,7 @@ void ExpressionParseMacroCall(struct ParseState *Parser, struct ExpressionStack ProgramFail(Parser, "'%s' is undefined", MacroName); ParserCopy(&MacroParser, &MDef->Body); - VariableStackFrameAdd(Parser, 0); + VariableStackFrameAdd(Parser, MacroName, 0); TopStackFrame->NumParams = ArgCount; TopStackFrame->ReturnValue = ReturnValue; for (Count = 0; Count < MDef->NumParams; Count++) @@ -1419,7 +1419,7 @@ void ExpressionParseFunctionCall(struct ParseState *Parser, struct ExpressionSta ProgramFail(Parser, "'%s' is undefined", FuncName); ParserCopy(&FuncParser, &FuncValue->Val->FuncDef.Body); - VariableStackFrameAdd(Parser, FuncValue->Val->FuncDef.Intrinsic ? FuncValue->Val->FuncDef.NumParams : 0); + VariableStackFrameAdd(Parser, FuncName, FuncValue->Val->FuncDef.Intrinsic ? FuncValue->Val->FuncDef.NumParams : 0); TopStackFrame->NumParams = ArgCount; TopStackFrame->ReturnValue = ReturnValue; for (Count = 0; Count < FuncValue->Val->FuncDef.NumParams; Count++) diff --git a/lex.c b/lex.c index ede1ea0..eb423ad 100644 --- a/lex.c +++ b/lex.c @@ -44,6 +44,7 @@ static struct ReservedWord ReservedWords[] = { "#ifdef", TokenHashIfdef, NULL }, { "#ifndef", TokenHashIfndef, NULL }, { "#include", TokenHashInclude, NULL }, + { "auto", TokenAutoType, NULL }, { "break", TokenBreak, NULL }, { "case", TokenCase, NULL }, { "char", TokenCharType, NULL }, @@ -741,7 +742,7 @@ void LexHashIfdef(struct ParseState *Parser, int IfNot) ProgramFail(Parser, "identifier expected"); /* is the identifier defined? */ - IsDefined = TableGet(&GlobalTable, IdentValue->Val->Identifier, &SavedValue, NULL, NULL); + IsDefined = TableGet(&GlobalTable, IdentValue->Val->Identifier, &SavedValue, NULL, NULL, NULL); if (Parser->HashIfEvaluateToLevel == Parser->HashIfLevel && ( (IsDefined && !IfNot) || (!IsDefined && IfNot)) ) { /* #if is active, evaluate to this new level */ @@ -763,7 +764,7 @@ void LexHashIf(struct ParseState *Parser) if (Token == TokenIdentifier) { /* look up a value from a macro definition */ - if (!TableGet(&GlobalTable, IdentValue->Val->Identifier, &SavedValue, NULL, NULL)) + if (!TableGet(&GlobalTable, IdentValue->Val->Identifier, &SavedValue, NULL, NULL, NULL)) ProgramFail(Parser, "'%s' is undefined", IdentValue->Val->Identifier); if (SavedValue->Typ->Base != TypeMacro) diff --git a/parse.c b/parse.c index c551b0c..72f93c9 100644 --- a/parse.c +++ b/parse.c @@ -105,7 +105,7 @@ struct Value *ParseFunctionDefinition(struct ParseState *Parser, struct ValueTyp else { /* add a parameter */ - TypeParse(&ParamParser, &ParamType, &ParamIdentifier); + TypeParse(&ParamParser, &ParamType, &ParamIdentifier, NULL); if (ParamType->Base == TypeVoid) { /* this isn't a real parameter at all - delete it */ @@ -157,7 +157,7 @@ struct Value *ParseFunctionDefinition(struct ParseState *Parser, struct ValueTyp FuncValue->Val->FuncDef.Body.Pos = LexCopyTokens(&FuncBody, Parser); /* is this function already in the global table? */ - if (TableGet(&GlobalTable, Identifier, &OldFuncValue, NULL, NULL)) + if (TableGet(&GlobalTable, Identifier, &OldFuncValue, NULL, NULL, NULL)) { if (OldFuncValue->Val->FuncDef.Body.Pos == NULL) { @@ -169,14 +169,14 @@ struct Value *ParseFunctionDefinition(struct ParseState *Parser, struct ValueTyp } } - if (!TableSet(&GlobalTable, Identifier, FuncValue, Parser->Line, Parser->CharacterPos)) + if (!TableSet(&GlobalTable, Identifier, FuncValue, (char *)Parser->FileName, Parser->Line, Parser->CharacterPos)) ProgramFail(Parser, "'%s' is already defined", Identifier); return FuncValue; } /* assign an initial value to a variable */ -void ParseDeclarationAssignment(struct ParseState *Parser, struct Value *NewVariable) +void ParseDeclarationAssignment(struct ParseState *Parser, struct Value *NewVariable, int DoAssignment) { struct Value *CValue; int ArrayIndex; @@ -200,7 +200,7 @@ void ParseDeclarationAssignment(struct ParseState *Parser, struct Value *NewVari if (!ExpressionParse(Parser, &CValue)) ProgramFail(Parser, "expression expected"); - if (Parser->Mode == RunModeRun) + if (Parser->Mode == RunModeRun && DoAssignment) { ExpressionAssign(Parser, ArrayElement, CValue, FALSE, NULL, 0, FALSE); VariableStackPop(Parser, CValue); @@ -222,7 +222,7 @@ void ParseDeclarationAssignment(struct ParseState *Parser, struct Value *NewVari if (!ExpressionParse(Parser, &CValue)) ProgramFail(Parser, "expression expected"); - if (Parser->Mode == RunModeRun) + if (Parser->Mode == RunModeRun && DoAssignment) { ExpressionAssign(Parser, NewVariable, CValue, FALSE, NULL, 0, FALSE); VariableStackPop(Parser, CValue); @@ -237,8 +237,10 @@ int ParseDeclaration(struct ParseState *Parser, enum LexToken Token) struct ValueType *BasicType; struct ValueType *Typ; struct Value *NewVariable = NULL; + int IsStatic = FALSE; + int FirstVisit = FALSE; - TypeParseFront(Parser, &BasicType); + TypeParseFront(Parser, &BasicType, &IsStatic); do { TypeParseIdentPart(Parser, BasicType, &Typ, &Identifier); @@ -259,13 +261,13 @@ int ParseDeclaration(struct ParseState *Parser, enum LexToken Token) ProgramFail(Parser, "can't define a void variable"); if (Parser->Mode == RunModeRun) - NewVariable = VariableDefineButIgnoreIdentical(Parser, Identifier, Typ); + NewVariable = VariableDefineButIgnoreIdentical(Parser, Identifier, Typ, IsStatic, &FirstVisit); if (LexGetToken(Parser, NULL, FALSE) == TokenAssign) { /* we're assigning an initial value */ LexGetToken(Parser, NULL, TRUE); - ParseDeclarationAssignment(Parser, NewVariable); + ParseDeclarationAssignment(Parser, NewVariable, !IsStatic || FirstVisit); } } } @@ -336,7 +338,7 @@ void ParseMacroDefinition(struct ParseState *Parser) LexToEndOfLine(Parser); MacroValue->Val->MacroDef.Body.Pos = LexCopyTokens(&MacroValue->Val->MacroDef.Body, Parser); - if (!TableSet(&GlobalTable, MacroNameStr, MacroValue, Parser->Line, Parser->CharacterPos)) + if (!TableSet(&GlobalTable, MacroNameStr, MacroValue, (char *)Parser->FileName, Parser->Line, Parser->CharacterPos)) ProgramFail(Parser, "'%s' is already defined", MacroNameStr); } @@ -458,7 +460,7 @@ void ParseTypedef(struct ParseState *Parser) char *TypeName; struct Value InitValue; - TypeParse(Parser, &Typ, &TypeName); + TypeParse(Parser, &Typ, &TypeName, NULL); if (Parser->Mode == RunModeRun) { @@ -619,6 +621,7 @@ enum ParseResult ParseStatement(struct ParseState *Parser, int CheckTrailingSemi case TokenSignedType: case TokenUnsignedType: case TokenStaticType: + case TokenAutoType: case TokenRegisterType: case TokenExternType: *Parser = PreState; diff --git a/picoc.h b/picoc.h index 6c65b24..3809260 100644 --- a/picoc.h +++ b/picoc.h @@ -80,12 +80,12 @@ enum LexToken /* 0x32 */ TokenSemicolon, TokenEllipsis, /* 0x34 */ TokenLeftBrace, TokenRightBrace, /* 0x36 */ TokenIntType, TokenCharType, TokenFloatType, TokenDoubleType, TokenVoidType, TokenEnumType, - /* 0x3c */ TokenLongType, TokenSignedType, TokenShortType, TokenStaticType, TokenRegisterType, TokenExternType, TokenStructType, TokenUnionType, TokenUnsignedType, TokenTypedef, - /* 0x45 */ TokenContinue, TokenDo, TokenElse, TokenFor, TokenIf, TokenWhile, TokenBreak, TokenSwitch, TokenCase, TokenDefault, TokenReturn, - /* 0x50 */ TokenHashDefine, TokenHashInclude, TokenHashIf, TokenHashIfdef, TokenHashIfndef, TokenHashElse, TokenHashEndif, - /* 0x57 */ TokenNew, TokenDelete, - /* 0x59 */ TokenOpenMacroBracket, - /* 0x5a */ TokenEOF, TokenEndOfLine, TokenEndOfFunction + /* 0x3c */ TokenLongType, TokenSignedType, TokenShortType, TokenStaticType, TokenAutoType, TokenRegisterType, TokenExternType, TokenStructType, TokenUnionType, TokenUnsignedType, TokenTypedef, + /* 0x46 */ TokenContinue, TokenDo, TokenElse, TokenFor, TokenIf, TokenWhile, TokenBreak, TokenSwitch, TokenCase, TokenDefault, TokenReturn, + /* 0x51 */ TokenHashDefine, TokenHashInclude, TokenHashIf, TokenHashIfdef, TokenHashIfndef, TokenHashElse, TokenHashEndif, + /* 0x58 */ TokenNew, TokenDelete, + /* 0x5a */ TokenOpenMacroBracket, + /* 0x5b */ TokenEOF, TokenEndOfLine, TokenEndOfFunction }; /* used in dynamic memory allocation */ @@ -110,13 +110,13 @@ enum RunMode struct ParseState { const unsigned char *Pos; - int Line; const char *FileName; + short int Line; + short int CharacterPos; enum RunMode Mode; /* whether to skip or run code */ int SearchLabel; /* what case label we're searching for */ - int HashIfLevel; - int HashIfEvaluateToLevel; - int CharacterPos; + short int HashIfLevel; + short int HashIfEvaluateToLevel; const char *SourceText; }; @@ -157,6 +157,7 @@ struct ValueType struct ValueType *Next; /* next item in the derived type list */ struct Table *Members; /* members of a struct or union */ int OnHeap; /* true if allocated on the heap */ + int StaticQualifier; /* true if it's a static */ }; /* function definition */ @@ -214,7 +215,8 @@ struct Value struct TableEntry { struct TableEntry *Next; /* next item in this hash chain */ - unsigned short DeclLine; /* where the variable was declared */ + const char *DeclFileName; /* where the variable was declared */ + unsigned short DeclLine; unsigned short DeclColumn; union TableEntryPayload @@ -240,6 +242,7 @@ struct Table struct StackFrame { struct ParseState ReturnParser; /* how we got here */ + const char *FuncName; /* the name of the function we're in */ struct Value *ReturnValue; /* copy the return value here */ struct Value **Parameter; /* array of parameter values */ int NumParams; /* the number of parameters */ @@ -329,8 +332,8 @@ void TableInit(); char *TableStrRegister(const char *Str); char *TableStrRegister2(const char *Str, int Len); void TableInitTable(struct Table *Tbl, struct TableEntry **HashTable, int Size, int OnHeap); -int TableSet(struct Table *Tbl, char *Key, struct Value *Val, int DeclLine, int DeclColumn); -int TableGet(struct Table *Tbl, const char *Key, struct Value **Val, int *DeclLine, int *DeclColumn); +int TableSet(struct Table *Tbl, char *Key, struct Value *Val, const char *DeclFileName, int DeclLine, int DeclColumn); +int TableGet(struct Table *Tbl, const char *Key, struct Value **Val, const char **DeclFileName, int *DeclLine, int *DeclColumn); struct Value *TableDelete(struct Table *Tbl, const char *Key); char *TableSetIdentifier(struct Table *Tbl, const char *Ident, int IdentLen); void TableStrFree(); @@ -374,9 +377,9 @@ int TypeSize(struct ValueType *Typ, int ArraySize, int Compact); int TypeSizeValue(struct Value *Val, int Compact); int TypeStackSizeValue(struct Value *Val); int TypeLastAccessibleOffset(struct Value *Val); -int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ); +int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ, int *IsStatic); void TypeParseIdentPart(struct ParseState *Parser, struct ValueType *BasicTyp, struct ValueType **Typ, char **Identifier); -void TypeParse(struct ParseState *Parser, struct ValueType **Typ, char **Identifier); +void TypeParse(struct ParseState *Parser, struct ValueType **Typ, char **Identifier, int *IsStatic); struct ValueType *TypeGetMatching(struct ParseState *Parser, struct ValueType *ParentType, enum BaseType Base, int ArraySize, const char *Identifier); struct ValueType *TypeCreateOpaqueStruct(struct ParseState *Parser, const char *StructName, int Size); @@ -404,11 +407,11 @@ struct Value *VariableAllocValueFromType(struct ParseState *Parser, struct Value struct Value *VariableAllocValueFromExistingData(struct ParseState *Parser, struct ValueType *Typ, union AnyValue *FromValue, int IsLValue, struct Value *LValueFrom); struct Value *VariableAllocValueShared(struct ParseState *Parser, struct Value *FromValue); struct Value *VariableDefine(struct ParseState *Parser, char *Ident, struct Value *InitValue, struct ValueType *Typ, int MakeWritable); -struct Value *VariableDefineButIgnoreIdentical(struct ParseState *Parser, char *Ident, struct ValueType *Typ); +struct Value *VariableDefineButIgnoreIdentical(struct ParseState *Parser, char *Ident, struct ValueType *Typ, int IsStatic, int *FirstVisit); int VariableDefined(const char *Ident); void VariableGet(struct ParseState *Parser, const char *Ident, struct Value **LVal); void VariableDefinePlatformVar(struct ParseState *Parser, char *Ident, struct ValueType *Typ, union AnyValue *FromValue, int IsWritable); -void VariableStackFrameAdd(struct ParseState *Parser, int NumParams); +void VariableStackFrameAdd(struct ParseState *Parser, const char *FuncName, int NumParams); void VariableStackFramePop(struct ParseState *Parser); struct Value *VariableStringLiteralGet(char *Ident); void VariableStringLiteralDefine(char *Ident, struct Value *Val); diff --git a/table.c b/table.c index 1dd0032..a02a41f 100644 --- a/table.c +++ b/table.c @@ -56,7 +56,7 @@ static struct TableEntry *TableSearch(struct Table *Tbl, const char *Key, int *A /* set an identifier to a value. returns FALSE if it already exists. * Key must be a shared string from TableStrRegister() */ -int TableSet(struct Table *Tbl, char *Key, struct Value *Val, int DeclLine, int DeclColumn) +int TableSet(struct Table *Tbl, char *Key, struct Value *Val, const char *DeclFileName, int DeclLine, int DeclColumn) { int AddAt; struct TableEntry *FoundEntry = TableSearch(Tbl, Key, &AddAt); @@ -64,6 +64,7 @@ int TableSet(struct Table *Tbl, char *Key, struct Value *Val, int DeclLine, int if (FoundEntry == NULL) { /* add it to the table */ struct TableEntry *NewEntry = VariableAlloc(NULL, sizeof(struct TableEntry), Tbl->OnHeap); + NewEntry->DeclFileName = DeclFileName; NewEntry->DeclLine = DeclLine; NewEntry->DeclColumn = DeclColumn; NewEntry->p.v.Key = Key; @@ -78,7 +79,7 @@ int TableSet(struct Table *Tbl, char *Key, struct Value *Val, int DeclLine, int /* find a value in a table. returns FALSE if not found. * Key must be a shared string from TableStrRegister() */ -int TableGet(struct Table *Tbl, const char *Key, struct Value **Val, int *DeclLine, int *DeclColumn) +int TableGet(struct Table *Tbl, const char *Key, struct Value **Val, const char **DeclFileName, int *DeclLine, int *DeclColumn) { int AddAt; struct TableEntry *FoundEntry = TableSearch(Tbl, Key, &AddAt); @@ -87,8 +88,9 @@ int TableGet(struct Table *Tbl, const char *Key, struct Value **Val, int *DeclLi *Val = FoundEntry->p.v.Val; - if (DeclLine != NULL) + if (DeclFileName != NULL) { + *DeclFileName = FoundEntry->DeclFileName; *DeclLine = FoundEntry->DeclLine; *DeclColumn = FoundEntry->DeclColumn; } diff --git a/type.c b/type.c index 5974c75..bf4f178 100644 --- a/type.c +++ b/type.c @@ -218,7 +218,7 @@ void TypeParseStruct(struct ParseState *Parser, struct ValueType **Typ, int IsSt TableInitTable((*Typ)->Members, (struct TableEntry **)((char *)(*Typ)->Members + sizeof(struct Table)), STRUCT_TABLE_SIZE, TRUE); do { - TypeParse(Parser, &MemberType, &MemberIdentifier); + TypeParse(Parser, &MemberType, &MemberIdentifier, NULL); if (MemberType == NULL || MemberIdentifier == NULL) ProgramFail(Parser, "invalid type in struct"); @@ -247,7 +247,7 @@ void TypeParseStruct(struct ParseState *Parser, struct ValueType **Typ, int IsSt (*Typ)->AlignBytes = MemberValue->Typ->AlignBytes; /* define it */ - if (!TableSet((*Typ)->Members, MemberIdentifier, MemberValue, Parser->Line, Parser->CharacterPos)) + if (!TableSet((*Typ)->Members, MemberIdentifier, MemberValue, Parser->FileName, Parser->Line, Parser->CharacterPos)) ProgramFail(Parser, "member '%s' already defined", &MemberIdentifier); if (LexGetToken(Parser, NULL, TRUE) != TokenSemicolon) @@ -333,20 +333,29 @@ void TypeParseEnum(struct ParseState *Parser, struct ValueType **Typ) } /* parse a type - just the basic type */ -int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ) +int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ, int *IsStatic) { struct ParseState Before; struct Value *LexerValue; enum LexToken Token; int Unsigned = FALSE; struct Value *VarValue; + int StaticQualifier = FALSE; *Typ = NULL; /* ignore leading type qualifiers */ ParserCopy(&Before, Parser); Token = LexGetToken(Parser, &LexerValue, TRUE); - while (Token == TokenStaticType || Token == TokenRegisterType || Token == TokenExternType) + while (Token == TokenStaticType || Token == TokenAutoType || Token == TokenRegisterType || Token == TokenExternType) + { + if (Token == TokenStaticType) + StaticQualifier = TRUE; + Token = LexGetToken(Parser, &LexerValue, TRUE); + } + + if (IsStatic != NULL) + *IsStatic = StaticQualifier; /* handle signed/unsigned with no trailing type */ if (Token == TokenSignedType || Token == TokenUnsignedType) @@ -454,7 +463,7 @@ void TypeParseIdentPart(struct ParseState *Parser, struct ValueType *BasicTyp, s if (*Typ != NULL) ProgramFail(Parser, "bad type declaration"); - TypeParse(Parser, Typ, Identifier); + TypeParse(Parser, Typ, Identifier, NULL); if (LexGetToken(Parser, NULL, TRUE) != TokenCloseBracket) ProgramFail(Parser, "')' expected"); break; @@ -489,11 +498,11 @@ void TypeParseIdentPart(struct ParseState *Parser, struct ValueType *BasicTyp, s } /* parse a type - a complete declaration including identifier */ -void TypeParse(struct ParseState *Parser, struct ValueType **Typ, char **Identifier) +void TypeParse(struct ParseState *Parser, struct ValueType **Typ, char **Identifier, int *IsStatic) { struct ValueType *BasicType; - TypeParseFront(Parser, &BasicType); + TypeParseFront(Parser, &BasicType, IsStatic); TypeParseIdentPart(Parser, BasicType, Typ, Identifier); } diff --git a/variable.c b/variable.c index d2f1b02..3e8ace6 100644 --- a/variable.c +++ b/variable.c @@ -161,24 +161,65 @@ struct Value *VariableDefine(struct ParseState *Parser, char *Ident, struct Valu AssignValue->IsLValue = MakeWritable; - if (!TableSet((TopStackFrame == NULL) ? &GlobalTable : &TopStackFrame->LocalTable, Ident, AssignValue, Parser ? Parser->Line : 0, Parser ? Parser->CharacterPos : 0)) + if (!TableSet((TopStackFrame == NULL) ? &GlobalTable : &TopStackFrame->LocalTable, Ident, AssignValue, Parser ? ((char *)Parser->FileName) : NULL, Parser ? Parser->Line : 0, Parser ? Parser->CharacterPos : 0)) ProgramFail(Parser, "'%s' is already defined", Ident); return AssignValue; } /* define a variable. Ident must be registered. If it's a redefinition from the same declaration don't throw an error */ -struct Value *VariableDefineButIgnoreIdentical(struct ParseState *Parser, char *Ident, struct ValueType *Typ) +struct Value *VariableDefineButIgnoreIdentical(struct ParseState *Parser, char *Ident, struct ValueType *Typ, int IsStatic, int *FirstVisit) { struct Value *ExistingValue; + const char *DeclFileName; int DeclLine; int DeclColumn; - if (Parser->Line != 0 && TableGet((TopStackFrame == NULL) ? &GlobalTable : &TopStackFrame->LocalTable, Ident, &ExistingValue, &DeclLine, &DeclColumn) - && DeclLine == Parser->Line && DeclColumn == Parser->CharacterPos) + if (IsStatic) + { + char MangledName[LINEBUFFER_MAX]; + char *MNPos = &MangledName[0]; + char *MNEnd = &MangledName[LINEBUFFER_MAX-1]; + const char *RegisteredMangledName; + + /* make the mangled static name (avoiding using sprintf() to minimise library impact) */ + memset(MangledName, '\0', sizeof(MangledName)); + *MNPos++ = '/'; + strncpy(MNPos, Parser->FileName, MNEnd - MNPos); + MNPos += strlen(MNPos); + + if (TopStackFrame != NULL) + { + /* we're inside a function */ + if (MNEnd - MNPos > 0) *MNPos++ = '/'; + strncpy(MNPos, TopStackFrame->FuncName, MNEnd - MNPos); + MNPos += strlen(MNPos); + } + + if (MNEnd - MNPos > 0) *MNPos++ = '/'; + strncpy(MNPos, Ident, MNEnd - MNPos); + RegisteredMangledName = TableStrRegister(MangledName); + + /* is this static already defined? */ + if (!TableGet(&GlobalTable, RegisteredMangledName, &ExistingValue, &DeclFileName, &DeclLine, &DeclColumn)) + { + /* define the mangled-named static variable store in the global scope */ + ExistingValue = VariableDefine(Parser, (char *)RegisteredMangledName, NULL, Typ, TRUE); + *FirstVisit = TRUE; + } + + /* static variable exists in the global scope - now make a mirroring variable in our own scope with the short name */ + VariableDefinePlatformVar(Parser, Ident, ExistingValue->Typ, ExistingValue->Val, TRUE); return ExistingValue; + } else - return VariableDefine(Parser, Ident, NULL, Typ, TRUE); + { + if (Parser->Line != 0 && TableGet((TopStackFrame == NULL) ? &GlobalTable : &TopStackFrame->LocalTable, Ident, &ExistingValue, &DeclFileName, &DeclLine, &DeclColumn) + && DeclFileName == Parser->FileName && DeclLine == Parser->Line && DeclColumn == Parser->CharacterPos) + return ExistingValue; + else + return VariableDefine(Parser, Ident, NULL, Typ, TRUE); + } } /* check if a variable with a given name is defined. Ident must be registered */ @@ -186,9 +227,9 @@ int VariableDefined(const char *Ident) { struct Value *FoundValue; - if (TopStackFrame == NULL || !TableGet(&TopStackFrame->LocalTable, Ident, &FoundValue, NULL, NULL)) + if (TopStackFrame == NULL || !TableGet(&TopStackFrame->LocalTable, Ident, &FoundValue, NULL, NULL, NULL)) { - if (!TableGet(&GlobalTable, Ident, &FoundValue, NULL, NULL)) + if (!TableGet(&GlobalTable, Ident, &FoundValue, NULL, NULL, NULL)) return FALSE; } @@ -198,9 +239,9 @@ int VariableDefined(const char *Ident) /* get the value of a variable. must be defined. Ident must be registered */ void VariableGet(struct ParseState *Parser, const char *Ident, struct Value **LVal) { - if (TopStackFrame == NULL || !TableGet(&TopStackFrame->LocalTable, Ident, LVal, NULL, NULL)) + if (TopStackFrame == NULL || !TableGet(&TopStackFrame->LocalTable, Ident, LVal, NULL, NULL, NULL)) { - if (!TableGet(&GlobalTable, Ident, LVal, NULL, NULL)) + if (!TableGet(&GlobalTable, Ident, LVal, NULL, NULL, NULL)) ProgramFail(Parser, "'%s' is undefined", Ident); } } @@ -212,7 +253,7 @@ void VariableDefinePlatformVar(struct ParseState *Parser, char *Ident, struct Va SomeValue->Typ = Typ; SomeValue->Val = FromValue; - if (!TableSet((TopStackFrame == NULL) ? &GlobalTable : &TopStackFrame->LocalTable, TableStrRegister(Ident), SomeValue, Parser ? Parser->Line : 0, Parser ? Parser->CharacterPos : 0)) + if (!TableSet((TopStackFrame == NULL) ? &GlobalTable : &TopStackFrame->LocalTable, TableStrRegister(Ident), SomeValue, Parser ? Parser->FileName : NULL, Parser ? Parser->Line : 0, Parser ? Parser->CharacterPos : 0)) ProgramFail(Parser, "'%s' is already defined", Ident); } @@ -243,7 +284,7 @@ void VariableStackPop(struct ParseState *Parser, struct Value *Var) } /* add a stack frame when doing a function call */ -void VariableStackFrameAdd(struct ParseState *Parser, int NumParams) +void VariableStackFrameAdd(struct ParseState *Parser, const char *FuncName, int NumParams) { struct StackFrame *NewFrame; @@ -253,6 +294,7 @@ void VariableStackFrameAdd(struct ParseState *Parser, int NumParams) ProgramFail(Parser, "out of memory"); ParserCopy(&NewFrame->ReturnParser, Parser); + NewFrame->FuncName = FuncName; NewFrame->Parameter = (NumParams > 0) ? ((void *)((char *)NewFrame + sizeof(struct StackFrame))) : NULL; TableInitTable(&NewFrame->LocalTable, &NewFrame->LocalHashTable[0], LOCAL_TABLE_SIZE, FALSE); NewFrame->PreviousStackFrame = TopStackFrame; @@ -275,7 +317,7 @@ struct Value *VariableStringLiteralGet(char *Ident) { struct Value *LVal = NULL; - if (TableGet(&StringLiteralTable, Ident, &LVal, NULL, NULL)) + if (TableGet(&StringLiteralTable, Ident, &LVal, NULL, NULL, NULL)) return LVal; else return NULL; @@ -284,7 +326,7 @@ struct Value *VariableStringLiteralGet(char *Ident) /* define a string literal. assumes that Ident is already registered */ void VariableStringLiteralDefine(char *Ident, struct Value *Val) { - TableSet(&StringLiteralTable, Ident, Val, 0, 0); + TableSet(&StringLiteralTable, Ident, Val, NULL, 0, 0); } /* check a pointer for validity and dereference it for use */