From d04337125e76f1597d61aba746b6662d0fb35136 Mon Sep 17 00:00:00 2001 From: Russell Joyce Date: Wed, 17 Jun 2020 19:57:10 +0100 Subject: [PATCH] Added support for extern variable declarations Effectively just ignores any declarations as global scope is shared across files in PicoC anyway, so the ultimate definition should be enough. --- README.md | 2 +- c-tests/extern.c | 9 +++++++++ c-tests/extern.h | 4 ++++ c-tests/extern2.c | 8 ++++++++ clibrary.c | 2 +- expression.c | 4 ++-- interpreter.h | 4 ++-- parse.c | 10 ++++++---- type.c | 17 ++++++++++++----- 9 files changed, 45 insertions(+), 15 deletions(-) create mode 100644 c-tests/extern.c create mode 100644 c-tests/extern.h create mode 100644 c-tests/extern2.c diff --git a/README.md b/README.md index ca84ad7..cb008d6 100644 --- a/README.md +++ b/README.md @@ -327,7 +327,7 @@ void PlatformLibraryInit() /* define an example structure */ Tokens = LexAnalyse(IntrinsicName, StructDefinition, strlen(StructDefinition), NULL); LexInitParser(&Parser, StructDefinition, Tokens, IntrinsicName, true, false); - TypeParse(&Parser, &ParsedType, &Identifier, &IsStatic, &IsVolatile); + TypeParse(&Parser, &ParsedType, &Identifier, &IsStatic, &IsExtern, &IsVolatile); HeapFree(Tokens); } ``` diff --git a/c-tests/extern.c b/c-tests/extern.c new file mode 100644 index 0000000..c3574d2 --- /dev/null +++ b/c-tests/extern.c @@ -0,0 +1,9 @@ +#include "extern.h" + +int a; + +int main(void) { + a = 1; + decrement(); + return a + b; +} diff --git a/c-tests/extern.h b/c-tests/extern.h new file mode 100644 index 0000000..0410662 --- /dev/null +++ b/c-tests/extern.h @@ -0,0 +1,4 @@ +extern int a; +extern long b; + +//void decrement(); diff --git a/c-tests/extern2.c b/c-tests/extern2.c new file mode 100644 index 0000000..c970658 --- /dev/null +++ b/c-tests/extern2.c @@ -0,0 +1,8 @@ +#include "extern.h" + +long b = 1; + +void decrement() { + a--; + b--; +} diff --git a/clibrary.c b/clibrary.c index 73df0b1..78ab9c7 100644 --- a/clibrary.c +++ b/clibrary.c @@ -46,7 +46,7 @@ void LibraryAdd(Picoc *pc, struct LibraryFunction *FuncList) strlen((char*)FuncList[Count].Prototype), NULL); LexInitParser(&Parser, pc, FuncList[Count].Prototype, Tokens, IntrinsicName, true, false); - TypeParse(&Parser, &ReturnType, &Identifier, NULL, NULL); + TypeParse(&Parser, &ReturnType, &Identifier, NULL, NULL, NULL); NewValue = ParseFunctionDefinition(&Parser, ReturnType, Identifier); NewValue->Val->FuncDef.Intrinsic = FuncList[Count].Func; HeapFreeMem(pc, Tokens); diff --git a/expression.c b/expression.c index 41be219..5c8419a 100644 --- a/expression.c +++ b/expression.c @@ -1469,7 +1469,7 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result) char *CastIdentifier; struct Value *CastTypeValue; - TypeParse(Parser, &CastType, &CastIdentifier, NULL, NULL); + TypeParse(Parser, &CastType, &CastIdentifier, NULL, NULL, NULL); if (LexGetToken(Parser, &LexValue, true) != TokenCloseBracket) ProgramFail(Parser, "brackets not closed"); @@ -1668,7 +1668,7 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result) PrefixState = false; ParserCopy(Parser, &PreState); - TypeParse(Parser, &Typ, &Identifier, NULL, NULL); + TypeParse(Parser, &Typ, &Identifier, NULL, NULL, NULL); TypeValue = VariableAllocValueFromType(Parser->pc, Parser, &Parser->pc->TypeType, false, NULL, false); TypeValue->Val->Typ = Typ; diff --git a/interpreter.h b/interpreter.h index cfee88a..3036d4f 100644 --- a/interpreter.h +++ b/interpreter.h @@ -575,11 +575,11 @@ extern int TypeSizeValue(struct Value *Val, int Compact); extern int TypeStackSizeValue(struct Value *Val); extern int TypeLastAccessibleOffset(Picoc *pc, struct Value *Val); extern int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ, - int *IsStatic, int *IsVolatile); + int *IsStatic, int *IsExtern, int *IsVolatile); extern void TypeParseIdentPart(struct ParseState *Parser, struct ValueType *BasicTyp, struct ValueType **Typ, char **Identifier); extern void TypeParse(struct ParseState *Parser, struct ValueType **Typ, - char **Identifier, int *IsStatic, int *IsVolatile); + char **Identifier, int *IsStatic, int *IsExtern, int *IsVolatile); extern struct ValueType *TypeGetMatching(Picoc *pc, struct ParseState *Parser, struct ValueType *ParentType, enum BaseType Base, int ArraySize, const char *Identifier, int AllowDuplicates); extern struct ValueType *TypeCreateOpaqueStruct(Picoc *pc, struct ParseState *Parser, diff --git a/parse.c b/parse.c index 591ce22..70fd420 100644 --- a/parse.c +++ b/parse.c @@ -122,7 +122,7 @@ struct Value *ParseFunctionDefinition(struct ParseState *Parser, break; } else { /* add a parameter */ - TypeParse(&ParamParser, &ParamType, &ParamIdentifier, NULL, NULL); + TypeParse(&ParamParser, &ParamType, &ParamIdentifier, NULL, NULL, NULL); if (ParamType->Base == TypeVoid) { /* this isn't a real parameter at all - delete it */ //ParamCount--; @@ -339,6 +339,7 @@ void ParseDeclarationAssignment(struct ParseState *Parser, int ParseDeclaration(struct ParseState *Parser, enum LexToken Token) { int IsStatic = false; + int IsExtern = false; int IsVolatile = false; int FirstVisit = false; char *Identifier; @@ -347,7 +348,7 @@ int ParseDeclaration(struct ParseState *Parser, enum LexToken Token) struct Value *NewVariable = NULL; Picoc *pc = Parser->pc; - TypeParseFront(Parser, &BasicType, &IsStatic, &IsVolatile); + TypeParseFront(Parser, &BasicType, &IsStatic, &IsExtern, &IsVolatile); do { TypeParseIdentPart(Parser, BasicType, &Typ, &Identifier); if ((Token != TokenVoidType && Token != TokenStructType && @@ -361,7 +362,8 @@ int ParseDeclaration(struct ParseState *Parser, enum LexToken Token) { ParseFunctionDefinition(Parser, Typ, Identifier); return false; - } else { + } else if (!IsExtern) { + /* extern means declaration rather than definition, so ignore */ if (Typ == &pc->VoidType && Identifier != pc->StrEmpty) ProgramFail(Parser, "can't define a void variable"); @@ -586,7 +588,7 @@ void ParseTypedef(struct ParseState *Parser) struct ValueType **TypPtr; struct Value InitValue; - TypeParse(Parser, &Typ, &TypeName, NULL, NULL); + TypeParse(Parser, &Typ, &TypeName, NULL, NULL, NULL); if (Parser->Mode == RunModeRun) { TypPtr = &Typ; diff --git a/type.c b/type.c index b6fedd2..a2af8d2 100644 --- a/type.c +++ b/type.c @@ -265,7 +265,7 @@ void TypeParseStruct(struct ParseState *Parser, struct ValueType **Typ, STRUCT_TABLE_SIZE, true); do { - TypeParse(Parser, &MemberType, &MemberIdentifier, NULL, NULL); + TypeParse(Parser, &MemberType, &MemberIdentifier, NULL, NULL, NULL); if (MemberType == NULL || MemberIdentifier == NULL) ProgramFail(Parser, "invalid type in struct"); @@ -393,10 +393,11 @@ void TypeParseEnum(struct ParseState *Parser, struct ValueType **Typ) /* parse a type - just the basic type */ int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ, - int *IsStatic, int *IsVolatile) + int *IsStatic, int *IsExtern, int *IsVolatile) { int Unsigned = false; int StaticQualifier = false; + int ExternQualifier = false; int VolatileQualifier = false; enum LexToken Token; struct ParseState Before; @@ -414,6 +415,8 @@ int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ, Token == TokenVolatileType || Token == TokenConstType) { if (Token == TokenStaticType) StaticQualifier = true; + else if (Token == TokenExternType) + ExternQualifier = true; else if (Token == TokenVolatileType) VolatileQualifier = true; @@ -427,6 +430,8 @@ int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ, FollowToken == TokenVolatileType || FollowToken == TokenConstType) { if (FollowToken == TokenStaticType) StaticQualifier = true; + else if (FollowToken == TokenExternType) + ExternQualifier = true; else if (FollowToken == TokenVolatileType) VolatileQualifier = true; @@ -436,6 +441,8 @@ int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ, if (IsStatic != NULL) *IsStatic = StaticQualifier; + if (IsExtern != NULL) + *IsExtern = ExternQualifier; if (IsVolatile != NULL) *IsVolatile = VolatileQualifier; @@ -570,7 +577,7 @@ void TypeParseIdentPart(struct ParseState *Parser, struct ValueType *BasicTyp, if (*Typ != NULL) ProgramFail(Parser, "bad type declaration"); - TypeParse(Parser, Typ, Identifier, NULL, NULL); + TypeParse(Parser, Typ, Identifier, NULL, NULL, NULL); if (LexGetToken(Parser, NULL, true) != TokenCloseBracket) ProgramFail(Parser, "')' expected"); break; @@ -606,11 +613,11 @@ void TypeParseIdentPart(struct ParseState *Parser, struct ValueType *BasicTyp, /* parse a type - a complete declaration including identifier */ void TypeParse(struct ParseState *Parser, struct ValueType **Typ, - char **Identifier, int *IsStatic, int *IsVolatile) + char **Identifier, int *IsStatic, int *IsExtern, int *IsVolatile) { struct ValueType *BasicType; - TypeParseFront(Parser, &BasicType, IsStatic, IsVolatile); + TypeParseFront(Parser, &BasicType, IsStatic, IsExtern, IsVolatile); TypeParseIdentPart(Parser, BasicType, Typ, Identifier); }