Added support for static type qualifiers.

git-svn-id: http://picoc.googlecode.com/svn/trunk@546 21eae674-98b7-11dd-bd71-f92a316d2d60
This commit is contained in:
zik.saleeba 2011-02-16 23:38:41 +00:00
parent bd601e45c3
commit cab5e8b2d8
8 changed files with 119 additions and 59 deletions

View file

@ -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); Tokens = LexAnalyse(IntrinsicName, FuncList[Count].Prototype, strlen((char *)FuncList[Count].Prototype), NULL);
LexInitParser(&Parser, FuncList[Count].Prototype, Tokens, IntrinsicName, TRUE); LexInitParser(&Parser, FuncList[Count].Prototype, Tokens, IntrinsicName, TRUE);
TypeParse(&Parser, &ReturnType, &Identifier); TypeParse(&Parser, &ReturnType, &Identifier, NULL);
NewValue = ParseFunctionDefinition(&Parser, ReturnType, Identifier); NewValue = ParseFunctionDefinition(&Parser, ReturnType, Identifier);
NewValue->Val->FuncDef.Intrinsic = FuncList[Count].Func; NewValue->Val->FuncDef.Intrinsic = FuncList[Count].Func;
HeapFreeMem(Tokens); HeapFreeMem(Tokens);

View file

@ -966,7 +966,7 @@ void ExpressionGetStructElement(struct ParseState *Parser, struct ExpressionStac
if (StructType->Base != TypeStruct && StructType->Base != TypeUnion) 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); 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); 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 */ /* 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; char *CastIdentifier;
struct Value *CastTypeValue; struct Value *CastTypeValue;
TypeParse(Parser, &CastType, &CastIdentifier); TypeParse(Parser, &CastType, &CastIdentifier, NULL);
if (LexGetToken(Parser, &LexValue, TRUE) != TokenCloseBracket) if (LexGetToken(Parser, &LexValue, TRUE) != TokenCloseBracket)
ProgramFail(Parser, "brackets not closed"); ProgramFail(Parser, "brackets not closed");
@ -1201,7 +1201,7 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
PrefixState = FALSE; PrefixState = FALSE;
ParserCopy(Parser, &PreState); ParserCopy(Parser, &PreState);
TypeParse(Parser, &Typ, &Identifier); TypeParse(Parser, &Typ, &Identifier, NULL);
TypeValue = VariableAllocValueFromType(Parser, &TypeType, FALSE, NULL, FALSE); TypeValue = VariableAllocValueFromType(Parser, &TypeType, FALSE, NULL, FALSE);
TypeValue->Val->Typ = Typ; TypeValue->Val->Typ = Typ;
ExpressionStackPushValueNode(Parser, &StackTop, TypeValue); ExpressionStackPushValueNode(Parser, &StackTop, TypeValue);
@ -1314,7 +1314,7 @@ void ExpressionParseMacroCall(struct ParseState *Parser, struct ExpressionStack
ProgramFail(Parser, "'%s' is undefined", MacroName); ProgramFail(Parser, "'%s' is undefined", MacroName);
ParserCopy(&MacroParser, &MDef->Body); ParserCopy(&MacroParser, &MDef->Body);
VariableStackFrameAdd(Parser, 0); VariableStackFrameAdd(Parser, MacroName, 0);
TopStackFrame->NumParams = ArgCount; TopStackFrame->NumParams = ArgCount;
TopStackFrame->ReturnValue = ReturnValue; TopStackFrame->ReturnValue = ReturnValue;
for (Count = 0; Count < MDef->NumParams; Count++) for (Count = 0; Count < MDef->NumParams; Count++)
@ -1419,7 +1419,7 @@ void ExpressionParseFunctionCall(struct ParseState *Parser, struct ExpressionSta
ProgramFail(Parser, "'%s' is undefined", FuncName); ProgramFail(Parser, "'%s' is undefined", FuncName);
ParserCopy(&FuncParser, &FuncValue->Val->FuncDef.Body); 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->NumParams = ArgCount;
TopStackFrame->ReturnValue = ReturnValue; TopStackFrame->ReturnValue = ReturnValue;
for (Count = 0; Count < FuncValue->Val->FuncDef.NumParams; Count++) for (Count = 0; Count < FuncValue->Val->FuncDef.NumParams; Count++)

5
lex.c
View file

@ -44,6 +44,7 @@ static struct ReservedWord ReservedWords[] =
{ "#ifdef", TokenHashIfdef, NULL }, { "#ifdef", TokenHashIfdef, NULL },
{ "#ifndef", TokenHashIfndef, NULL }, { "#ifndef", TokenHashIfndef, NULL },
{ "#include", TokenHashInclude, NULL }, { "#include", TokenHashInclude, NULL },
{ "auto", TokenAutoType, NULL },
{ "break", TokenBreak, NULL }, { "break", TokenBreak, NULL },
{ "case", TokenCase, NULL }, { "case", TokenCase, NULL },
{ "char", TokenCharType, NULL }, { "char", TokenCharType, NULL },
@ -741,7 +742,7 @@ void LexHashIfdef(struct ParseState *Parser, int IfNot)
ProgramFail(Parser, "identifier expected"); ProgramFail(Parser, "identifier expected");
/* is the identifier defined? */ /* 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 (Parser->HashIfEvaluateToLevel == Parser->HashIfLevel && ( (IsDefined && !IfNot) || (!IsDefined && IfNot)) )
{ {
/* #if is active, evaluate to this new level */ /* #if is active, evaluate to this new level */
@ -763,7 +764,7 @@ void LexHashIf(struct ParseState *Parser)
if (Token == TokenIdentifier) if (Token == TokenIdentifier)
{ {
/* look up a value from a macro definition */ /* 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); ProgramFail(Parser, "'%s' is undefined", IdentValue->Val->Identifier);
if (SavedValue->Typ->Base != TypeMacro) if (SavedValue->Typ->Base != TypeMacro)

25
parse.c
View file

@ -105,7 +105,7 @@ struct Value *ParseFunctionDefinition(struct ParseState *Parser, struct ValueTyp
else else
{ {
/* add a parameter */ /* add a parameter */
TypeParse(&ParamParser, &ParamType, &ParamIdentifier); TypeParse(&ParamParser, &ParamType, &ParamIdentifier, NULL);
if (ParamType->Base == TypeVoid) if (ParamType->Base == TypeVoid)
{ {
/* this isn't a real parameter at all - delete it */ /* 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); FuncValue->Val->FuncDef.Body.Pos = LexCopyTokens(&FuncBody, Parser);
/* is this function already in the global table? */ /* 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) 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); ProgramFail(Parser, "'%s' is already defined", Identifier);
return FuncValue; return FuncValue;
} }
/* assign an initial value to a variable */ /* 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; struct Value *CValue;
int ArrayIndex; int ArrayIndex;
@ -200,7 +200,7 @@ void ParseDeclarationAssignment(struct ParseState *Parser, struct Value *NewVari
if (!ExpressionParse(Parser, &CValue)) if (!ExpressionParse(Parser, &CValue))
ProgramFail(Parser, "expression expected"); ProgramFail(Parser, "expression expected");
if (Parser->Mode == RunModeRun) if (Parser->Mode == RunModeRun && DoAssignment)
{ {
ExpressionAssign(Parser, ArrayElement, CValue, FALSE, NULL, 0, FALSE); ExpressionAssign(Parser, ArrayElement, CValue, FALSE, NULL, 0, FALSE);
VariableStackPop(Parser, CValue); VariableStackPop(Parser, CValue);
@ -222,7 +222,7 @@ void ParseDeclarationAssignment(struct ParseState *Parser, struct Value *NewVari
if (!ExpressionParse(Parser, &CValue)) if (!ExpressionParse(Parser, &CValue))
ProgramFail(Parser, "expression expected"); ProgramFail(Parser, "expression expected");
if (Parser->Mode == RunModeRun) if (Parser->Mode == RunModeRun && DoAssignment)
{ {
ExpressionAssign(Parser, NewVariable, CValue, FALSE, NULL, 0, FALSE); ExpressionAssign(Parser, NewVariable, CValue, FALSE, NULL, 0, FALSE);
VariableStackPop(Parser, CValue); VariableStackPop(Parser, CValue);
@ -237,8 +237,10 @@ int ParseDeclaration(struct ParseState *Parser, enum LexToken Token)
struct ValueType *BasicType; struct ValueType *BasicType;
struct ValueType *Typ; struct ValueType *Typ;
struct Value *NewVariable = NULL; struct Value *NewVariable = NULL;
int IsStatic = FALSE;
int FirstVisit = FALSE;
TypeParseFront(Parser, &BasicType); TypeParseFront(Parser, &BasicType, &IsStatic);
do do
{ {
TypeParseIdentPart(Parser, BasicType, &Typ, &Identifier); 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"); ProgramFail(Parser, "can't define a void variable");
if (Parser->Mode == RunModeRun) if (Parser->Mode == RunModeRun)
NewVariable = VariableDefineButIgnoreIdentical(Parser, Identifier, Typ); NewVariable = VariableDefineButIgnoreIdentical(Parser, Identifier, Typ, IsStatic, &FirstVisit);
if (LexGetToken(Parser, NULL, FALSE) == TokenAssign) if (LexGetToken(Parser, NULL, FALSE) == TokenAssign)
{ {
/* we're assigning an initial value */ /* we're assigning an initial value */
LexGetToken(Parser, NULL, TRUE); LexGetToken(Parser, NULL, TRUE);
ParseDeclarationAssignment(Parser, NewVariable); ParseDeclarationAssignment(Parser, NewVariable, !IsStatic || FirstVisit);
} }
} }
} }
@ -336,7 +338,7 @@ void ParseMacroDefinition(struct ParseState *Parser)
LexToEndOfLine(Parser); LexToEndOfLine(Parser);
MacroValue->Val->MacroDef.Body.Pos = LexCopyTokens(&MacroValue->Val->MacroDef.Body, 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); ProgramFail(Parser, "'%s' is already defined", MacroNameStr);
} }
@ -458,7 +460,7 @@ void ParseTypedef(struct ParseState *Parser)
char *TypeName; char *TypeName;
struct Value InitValue; struct Value InitValue;
TypeParse(Parser, &Typ, &TypeName); TypeParse(Parser, &Typ, &TypeName, NULL);
if (Parser->Mode == RunModeRun) if (Parser->Mode == RunModeRun)
{ {
@ -619,6 +621,7 @@ enum ParseResult ParseStatement(struct ParseState *Parser, int CheckTrailingSemi
case TokenSignedType: case TokenSignedType:
case TokenUnsignedType: case TokenUnsignedType:
case TokenStaticType: case TokenStaticType:
case TokenAutoType:
case TokenRegisterType: case TokenRegisterType:
case TokenExternType: case TokenExternType:
*Parser = PreState; *Parser = PreState;

37
picoc.h
View file

@ -80,12 +80,12 @@ enum LexToken
/* 0x32 */ TokenSemicolon, TokenEllipsis, /* 0x32 */ TokenSemicolon, TokenEllipsis,
/* 0x34 */ TokenLeftBrace, TokenRightBrace, /* 0x34 */ TokenLeftBrace, TokenRightBrace,
/* 0x36 */ TokenIntType, TokenCharType, TokenFloatType, TokenDoubleType, TokenVoidType, TokenEnumType, /* 0x36 */ TokenIntType, TokenCharType, TokenFloatType, TokenDoubleType, TokenVoidType, TokenEnumType,
/* 0x3c */ TokenLongType, TokenSignedType, TokenShortType, TokenStaticType, TokenRegisterType, TokenExternType, TokenStructType, TokenUnionType, TokenUnsignedType, TokenTypedef, /* 0x3c */ TokenLongType, TokenSignedType, TokenShortType, TokenStaticType, TokenAutoType, TokenRegisterType, TokenExternType, TokenStructType, TokenUnionType, TokenUnsignedType, TokenTypedef,
/* 0x45 */ TokenContinue, TokenDo, TokenElse, TokenFor, TokenIf, TokenWhile, TokenBreak, TokenSwitch, TokenCase, TokenDefault, TokenReturn, /* 0x46 */ TokenContinue, TokenDo, TokenElse, TokenFor, TokenIf, TokenWhile, TokenBreak, TokenSwitch, TokenCase, TokenDefault, TokenReturn,
/* 0x50 */ TokenHashDefine, TokenHashInclude, TokenHashIf, TokenHashIfdef, TokenHashIfndef, TokenHashElse, TokenHashEndif, /* 0x51 */ TokenHashDefine, TokenHashInclude, TokenHashIf, TokenHashIfdef, TokenHashIfndef, TokenHashElse, TokenHashEndif,
/* 0x57 */ TokenNew, TokenDelete, /* 0x58 */ TokenNew, TokenDelete,
/* 0x59 */ TokenOpenMacroBracket, /* 0x5a */ TokenOpenMacroBracket,
/* 0x5a */ TokenEOF, TokenEndOfLine, TokenEndOfFunction /* 0x5b */ TokenEOF, TokenEndOfLine, TokenEndOfFunction
}; };
/* used in dynamic memory allocation */ /* used in dynamic memory allocation */
@ -110,13 +110,13 @@ enum RunMode
struct ParseState struct ParseState
{ {
const unsigned char *Pos; const unsigned char *Pos;
int Line;
const char *FileName; const char *FileName;
short int Line;
short int CharacterPos;
enum RunMode Mode; /* whether to skip or run code */ enum RunMode Mode; /* whether to skip or run code */
int SearchLabel; /* what case label we're searching for */ int SearchLabel; /* what case label we're searching for */
int HashIfLevel; short int HashIfLevel;
int HashIfEvaluateToLevel; short int HashIfEvaluateToLevel;
int CharacterPos;
const char *SourceText; const char *SourceText;
}; };
@ -157,6 +157,7 @@ struct ValueType
struct ValueType *Next; /* next item in the derived type list */ struct ValueType *Next; /* next item in the derived type list */
struct Table *Members; /* members of a struct or union */ struct Table *Members; /* members of a struct or union */
int OnHeap; /* true if allocated on the heap */ int OnHeap; /* true if allocated on the heap */
int StaticQualifier; /* true if it's a static */
}; };
/* function definition */ /* function definition */
@ -214,7 +215,8 @@ struct Value
struct TableEntry struct TableEntry
{ {
struct TableEntry *Next; /* next item in this hash chain */ 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; unsigned short DeclColumn;
union TableEntryPayload union TableEntryPayload
@ -240,6 +242,7 @@ struct Table
struct StackFrame struct StackFrame
{ {
struct ParseState ReturnParser; /* how we got here */ 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 *ReturnValue; /* copy the return value here */
struct Value **Parameter; /* array of parameter values */ struct Value **Parameter; /* array of parameter values */
int NumParams; /* the number of parameters */ int NumParams; /* the number of parameters */
@ -329,8 +332,8 @@ void TableInit();
char *TableStrRegister(const char *Str); char *TableStrRegister(const char *Str);
char *TableStrRegister2(const char *Str, int Len); char *TableStrRegister2(const char *Str, int Len);
void TableInitTable(struct Table *Tbl, struct TableEntry **HashTable, int Size, int OnHeap); 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 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, 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); struct Value *TableDelete(struct Table *Tbl, const char *Key);
char *TableSetIdentifier(struct Table *Tbl, const char *Ident, int IdentLen); char *TableSetIdentifier(struct Table *Tbl, const char *Ident, int IdentLen);
void TableStrFree(); void TableStrFree();
@ -374,9 +377,9 @@ int TypeSize(struct ValueType *Typ, int ArraySize, int Compact);
int TypeSizeValue(struct Value *Val, int Compact); int TypeSizeValue(struct Value *Val, int Compact);
int TypeStackSizeValue(struct Value *Val); int TypeStackSizeValue(struct Value *Val);
int TypeLastAccessibleOffset(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 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 *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); 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 *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 *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 *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); int VariableDefined(const char *Ident);
void VariableGet(struct ParseState *Parser, const char *Ident, struct Value **LVal); 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 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); void VariableStackFramePop(struct ParseState *Parser);
struct Value *VariableStringLiteralGet(char *Ident); struct Value *VariableStringLiteralGet(char *Ident);
void VariableStringLiteralDefine(char *Ident, struct Value *Val); void VariableStringLiteralDefine(char *Ident, struct Value *Val);

View file

@ -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. /* set an identifier to a value. returns FALSE if it already exists.
* Key must be a shared string from TableStrRegister() */ * 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; int AddAt;
struct TableEntry *FoundEntry = TableSearch(Tbl, Key, &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) if (FoundEntry == NULL)
{ /* add it to the table */ { /* add it to the table */
struct TableEntry *NewEntry = VariableAlloc(NULL, sizeof(struct TableEntry), Tbl->OnHeap); struct TableEntry *NewEntry = VariableAlloc(NULL, sizeof(struct TableEntry), Tbl->OnHeap);
NewEntry->DeclFileName = DeclFileName;
NewEntry->DeclLine = DeclLine; NewEntry->DeclLine = DeclLine;
NewEntry->DeclColumn = DeclColumn; NewEntry->DeclColumn = DeclColumn;
NewEntry->p.v.Key = Key; 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. /* find a value in a table. returns FALSE if not found.
* Key must be a shared string from TableStrRegister() */ * 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; int AddAt;
struct TableEntry *FoundEntry = TableSearch(Tbl, Key, &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; *Val = FoundEntry->p.v.Val;
if (DeclLine != NULL) if (DeclFileName != NULL)
{ {
*DeclFileName = FoundEntry->DeclFileName;
*DeclLine = FoundEntry->DeclLine; *DeclLine = FoundEntry->DeclLine;
*DeclColumn = FoundEntry->DeclColumn; *DeclColumn = FoundEntry->DeclColumn;
} }

23
type.c
View file

@ -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); TableInitTable((*Typ)->Members, (struct TableEntry **)((char *)(*Typ)->Members + sizeof(struct Table)), STRUCT_TABLE_SIZE, TRUE);
do { do {
TypeParse(Parser, &MemberType, &MemberIdentifier); TypeParse(Parser, &MemberType, &MemberIdentifier, NULL);
if (MemberType == NULL || MemberIdentifier == NULL) if (MemberType == NULL || MemberIdentifier == NULL)
ProgramFail(Parser, "invalid type in struct"); 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; (*Typ)->AlignBytes = MemberValue->Typ->AlignBytes;
/* define it */ /* 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); ProgramFail(Parser, "member '%s' already defined", &MemberIdentifier);
if (LexGetToken(Parser, NULL, TRUE) != TokenSemicolon) 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 */ /* 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 ParseState Before;
struct Value *LexerValue; struct Value *LexerValue;
enum LexToken Token; enum LexToken Token;
int Unsigned = FALSE; int Unsigned = FALSE;
struct Value *VarValue; struct Value *VarValue;
int StaticQualifier = FALSE;
*Typ = NULL; *Typ = NULL;
/* ignore leading type qualifiers */ /* ignore leading type qualifiers */
ParserCopy(&Before, Parser); ParserCopy(&Before, Parser);
Token = LexGetToken(Parser, &LexerValue, TRUE); 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); Token = LexGetToken(Parser, &LexerValue, TRUE);
}
if (IsStatic != NULL)
*IsStatic = StaticQualifier;
/* handle signed/unsigned with no trailing type */ /* handle signed/unsigned with no trailing type */
if (Token == TokenSignedType || Token == TokenUnsignedType) if (Token == TokenSignedType || Token == TokenUnsignedType)
@ -454,7 +463,7 @@ void TypeParseIdentPart(struct ParseState *Parser, struct ValueType *BasicTyp, s
if (*Typ != NULL) if (*Typ != NULL)
ProgramFail(Parser, "bad type declaration"); ProgramFail(Parser, "bad type declaration");
TypeParse(Parser, Typ, Identifier); TypeParse(Parser, Typ, Identifier, NULL);
if (LexGetToken(Parser, NULL, TRUE) != TokenCloseBracket) if (LexGetToken(Parser, NULL, TRUE) != TokenCloseBracket)
ProgramFail(Parser, "')' expected"); ProgramFail(Parser, "')' expected");
break; break;
@ -489,11 +498,11 @@ void TypeParseIdentPart(struct ParseState *Parser, struct ValueType *BasicTyp, s
} }
/* parse a type - a complete declaration including identifier */ /* 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; struct ValueType *BasicType;
TypeParseFront(Parser, &BasicType); TypeParseFront(Parser, &BasicType, IsStatic);
TypeParseIdentPart(Parser, BasicType, Typ, Identifier); TypeParseIdentPart(Parser, BasicType, Typ, Identifier);
} }

View file

@ -161,24 +161,65 @@ struct Value *VariableDefine(struct ParseState *Parser, char *Ident, struct Valu
AssignValue->IsLValue = MakeWritable; 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); ProgramFail(Parser, "'%s' is already defined", Ident);
return AssignValue; return AssignValue;
} }
/* define a variable. Ident must be registered. If it's a redefinition from the same declaration don't throw an error */ /* 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; struct Value *ExistingValue;
const char *DeclFileName;
int DeclLine; int DeclLine;
int DeclColumn; int DeclColumn;
if (Parser->Line != 0 && TableGet((TopStackFrame == NULL) ? &GlobalTable : &TopStackFrame->LocalTable, Ident, &ExistingValue, &DeclLine, &DeclColumn) if (IsStatic)
&& DeclLine == Parser->Line && DeclColumn == Parser->CharacterPos) {
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; return ExistingValue;
}
else 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 */ /* 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; 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; return FALSE;
} }
@ -198,9 +239,9 @@ int VariableDefined(const char *Ident)
/* get the value of a variable. must be defined. Ident must be registered */ /* get the value of a variable. must be defined. Ident must be registered */
void VariableGet(struct ParseState *Parser, const char *Ident, struct Value **LVal) 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); ProgramFail(Parser, "'%s' is undefined", Ident);
} }
} }
@ -212,7 +253,7 @@ void VariableDefinePlatformVar(struct ParseState *Parser, char *Ident, struct Va
SomeValue->Typ = Typ; SomeValue->Typ = Typ;
SomeValue->Val = FromValue; 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); 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 */ /* 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; struct StackFrame *NewFrame;
@ -253,6 +294,7 @@ void VariableStackFrameAdd(struct ParseState *Parser, int NumParams)
ProgramFail(Parser, "out of memory"); ProgramFail(Parser, "out of memory");
ParserCopy(&NewFrame->ReturnParser, Parser); ParserCopy(&NewFrame->ReturnParser, Parser);
NewFrame->FuncName = FuncName;
NewFrame->Parameter = (NumParams > 0) ? ((void *)((char *)NewFrame + sizeof(struct StackFrame))) : NULL; NewFrame->Parameter = (NumParams > 0) ? ((void *)((char *)NewFrame + sizeof(struct StackFrame))) : NULL;
TableInitTable(&NewFrame->LocalTable, &NewFrame->LocalHashTable[0], LOCAL_TABLE_SIZE, FALSE); TableInitTable(&NewFrame->LocalTable, &NewFrame->LocalHashTable[0], LOCAL_TABLE_SIZE, FALSE);
NewFrame->PreviousStackFrame = TopStackFrame; NewFrame->PreviousStackFrame = TopStackFrame;
@ -275,7 +317,7 @@ struct Value *VariableStringLiteralGet(char *Ident)
{ {
struct Value *LVal = NULL; struct Value *LVal = NULL;
if (TableGet(&StringLiteralTable, Ident, &LVal, NULL, NULL)) if (TableGet(&StringLiteralTable, Ident, &LVal, NULL, NULL, NULL))
return LVal; return LVal;
else else
return NULL; return NULL;
@ -284,7 +326,7 @@ struct Value *VariableStringLiteralGet(char *Ident)
/* define a string literal. assumes that Ident is already registered */ /* define a string literal. assumes that Ident is already registered */
void VariableStringLiteralDefine(char *Ident, struct Value *Val) 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 */ /* check a pointer for validity and dereference it for use */