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.
This commit is contained in:
Russell Joyce 2020-06-17 19:57:10 +01:00
parent 875a635648
commit d04337125e
No known key found for this signature in database
GPG key ID: 3D46BD9018AF7B72
9 changed files with 45 additions and 15 deletions

View file

@ -327,7 +327,7 @@ void PlatformLibraryInit()
/* define an example structure */ /* define an example structure */
Tokens = LexAnalyse(IntrinsicName, StructDefinition, strlen(StructDefinition), NULL); Tokens = LexAnalyse(IntrinsicName, StructDefinition, strlen(StructDefinition), NULL);
LexInitParser(&Parser, StructDefinition, Tokens, IntrinsicName, true, false); LexInitParser(&Parser, StructDefinition, Tokens, IntrinsicName, true, false);
TypeParse(&Parser, &ParsedType, &Identifier, &IsStatic, &IsVolatile); TypeParse(&Parser, &ParsedType, &Identifier, &IsStatic, &IsExtern, &IsVolatile);
HeapFree(Tokens); HeapFree(Tokens);
} }
``` ```

9
c-tests/extern.c Normal file
View file

@ -0,0 +1,9 @@
#include "extern.h"
int a;
int main(void) {
a = 1;
decrement();
return a + b;
}

4
c-tests/extern.h Normal file
View file

@ -0,0 +1,4 @@
extern int a;
extern long b;
//void decrement();

8
c-tests/extern2.c Normal file
View file

@ -0,0 +1,8 @@
#include "extern.h"
long b = 1;
void decrement() {
a--;
b--;
}

View file

@ -46,7 +46,7 @@ void LibraryAdd(Picoc *pc, struct LibraryFunction *FuncList)
strlen((char*)FuncList[Count].Prototype), NULL); strlen((char*)FuncList[Count].Prototype), NULL);
LexInitParser(&Parser, pc, FuncList[Count].Prototype, Tokens, LexInitParser(&Parser, pc, FuncList[Count].Prototype, Tokens,
IntrinsicName, true, false); IntrinsicName, true, false);
TypeParse(&Parser, &ReturnType, &Identifier, NULL, NULL); TypeParse(&Parser, &ReturnType, &Identifier, NULL, NULL, 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(pc, Tokens); HeapFreeMem(pc, Tokens);

View file

@ -1469,7 +1469,7 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
char *CastIdentifier; char *CastIdentifier;
struct Value *CastTypeValue; struct Value *CastTypeValue;
TypeParse(Parser, &CastType, &CastIdentifier, NULL, NULL); TypeParse(Parser, &CastType, &CastIdentifier, NULL, NULL, NULL);
if (LexGetToken(Parser, &LexValue, true) != TokenCloseBracket) if (LexGetToken(Parser, &LexValue, true) != TokenCloseBracket)
ProgramFail(Parser, "brackets not closed"); ProgramFail(Parser, "brackets not closed");
@ -1668,7 +1668,7 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
PrefixState = false; PrefixState = false;
ParserCopy(Parser, &PreState); ParserCopy(Parser, &PreState);
TypeParse(Parser, &Typ, &Identifier, NULL, NULL); TypeParse(Parser, &Typ, &Identifier, NULL, NULL, NULL);
TypeValue = VariableAllocValueFromType(Parser->pc, Parser, TypeValue = VariableAllocValueFromType(Parser->pc, Parser,
&Parser->pc->TypeType, false, NULL, false); &Parser->pc->TypeType, false, NULL, false);
TypeValue->Val->Typ = Typ; TypeValue->Val->Typ = Typ;

View file

@ -575,11 +575,11 @@ extern int TypeSizeValue(struct Value *Val, int Compact);
extern int TypeStackSizeValue(struct Value *Val); extern int TypeStackSizeValue(struct Value *Val);
extern int TypeLastAccessibleOffset(Picoc *pc, struct Value *Val); extern int TypeLastAccessibleOffset(Picoc *pc, struct Value *Val);
extern int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ, 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, extern void TypeParseIdentPart(struct ParseState *Parser,
struct ValueType *BasicTyp, struct ValueType **Typ, char **Identifier); struct ValueType *BasicTyp, struct ValueType **Typ, char **Identifier);
extern void TypeParse(struct ParseState *Parser, struct ValueType **Typ, 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, extern struct ValueType *TypeGetMatching(Picoc *pc, struct ParseState *Parser,
struct ValueType *ParentType, enum BaseType Base, int ArraySize, const char *Identifier, int AllowDuplicates); struct ValueType *ParentType, enum BaseType Base, int ArraySize, const char *Identifier, int AllowDuplicates);
extern struct ValueType *TypeCreateOpaqueStruct(Picoc *pc, struct ParseState *Parser, extern struct ValueType *TypeCreateOpaqueStruct(Picoc *pc, struct ParseState *Parser,

10
parse.c
View file

@ -122,7 +122,7 @@ struct Value *ParseFunctionDefinition(struct ParseState *Parser,
break; break;
} else { } else {
/* add a parameter */ /* add a parameter */
TypeParse(&ParamParser, &ParamType, &ParamIdentifier, NULL, NULL); TypeParse(&ParamParser, &ParamType, &ParamIdentifier, NULL, NULL, 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 */
//ParamCount--; //ParamCount--;
@ -339,6 +339,7 @@ void ParseDeclarationAssignment(struct ParseState *Parser,
int ParseDeclaration(struct ParseState *Parser, enum LexToken Token) int ParseDeclaration(struct ParseState *Parser, enum LexToken Token)
{ {
int IsStatic = false; int IsStatic = false;
int IsExtern = false;
int IsVolatile = false; int IsVolatile = false;
int FirstVisit = false; int FirstVisit = false;
char *Identifier; char *Identifier;
@ -347,7 +348,7 @@ int ParseDeclaration(struct ParseState *Parser, enum LexToken Token)
struct Value *NewVariable = NULL; struct Value *NewVariable = NULL;
Picoc *pc = Parser->pc; Picoc *pc = Parser->pc;
TypeParseFront(Parser, &BasicType, &IsStatic, &IsVolatile); TypeParseFront(Parser, &BasicType, &IsStatic, &IsExtern, &IsVolatile);
do { do {
TypeParseIdentPart(Parser, BasicType, &Typ, &Identifier); TypeParseIdentPart(Parser, BasicType, &Typ, &Identifier);
if ((Token != TokenVoidType && Token != TokenStructType && if ((Token != TokenVoidType && Token != TokenStructType &&
@ -361,7 +362,8 @@ int ParseDeclaration(struct ParseState *Parser, enum LexToken Token)
{ {
ParseFunctionDefinition(Parser, Typ, Identifier); ParseFunctionDefinition(Parser, Typ, Identifier);
return false; return false;
} else { } else if (!IsExtern) {
/* extern means declaration rather than definition, so ignore */
if (Typ == &pc->VoidType && Identifier != pc->StrEmpty) if (Typ == &pc->VoidType && Identifier != pc->StrEmpty)
ProgramFail(Parser, "can't define a void variable"); ProgramFail(Parser, "can't define a void variable");
@ -586,7 +588,7 @@ void ParseTypedef(struct ParseState *Parser)
struct ValueType **TypPtr; struct ValueType **TypPtr;
struct Value InitValue; struct Value InitValue;
TypeParse(Parser, &Typ, &TypeName, NULL, NULL); TypeParse(Parser, &Typ, &TypeName, NULL, NULL, NULL);
if (Parser->Mode == RunModeRun) { if (Parser->Mode == RunModeRun) {
TypPtr = &Typ; TypPtr = &Typ;

17
type.c
View file

@ -265,7 +265,7 @@ void TypeParseStruct(struct ParseState *Parser, struct ValueType **Typ,
STRUCT_TABLE_SIZE, true); STRUCT_TABLE_SIZE, true);
do { do {
TypeParse(Parser, &MemberType, &MemberIdentifier, NULL, NULL); TypeParse(Parser, &MemberType, &MemberIdentifier, NULL, NULL, NULL);
if (MemberType == NULL || MemberIdentifier == NULL) if (MemberType == NULL || MemberIdentifier == NULL)
ProgramFail(Parser, "invalid type in struct"); 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 */ /* 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, int *IsVolatile) int *IsStatic, int *IsExtern, int *IsVolatile)
{ {
int Unsigned = false; int Unsigned = false;
int StaticQualifier = false; int StaticQualifier = false;
int ExternQualifier = false;
int VolatileQualifier = false; int VolatileQualifier = false;
enum LexToken Token; enum LexToken Token;
struct ParseState Before; struct ParseState Before;
@ -414,6 +415,8 @@ int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ,
Token == TokenVolatileType || Token == TokenConstType) { Token == TokenVolatileType || Token == TokenConstType) {
if (Token == TokenStaticType) if (Token == TokenStaticType)
StaticQualifier = true; StaticQualifier = true;
else if (Token == TokenExternType)
ExternQualifier = true;
else if (Token == TokenVolatileType) else if (Token == TokenVolatileType)
VolatileQualifier = true; VolatileQualifier = true;
@ -427,6 +430,8 @@ int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ,
FollowToken == TokenVolatileType || FollowToken == TokenConstType) { FollowToken == TokenVolatileType || FollowToken == TokenConstType) {
if (FollowToken == TokenStaticType) if (FollowToken == TokenStaticType)
StaticQualifier = true; StaticQualifier = true;
else if (FollowToken == TokenExternType)
ExternQualifier = true;
else if (FollowToken == TokenVolatileType) else if (FollowToken == TokenVolatileType)
VolatileQualifier = true; VolatileQualifier = true;
@ -436,6 +441,8 @@ int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ,
if (IsStatic != NULL) if (IsStatic != NULL)
*IsStatic = StaticQualifier; *IsStatic = StaticQualifier;
if (IsExtern != NULL)
*IsExtern = ExternQualifier;
if (IsVolatile != NULL) if (IsVolatile != NULL)
*IsVolatile = VolatileQualifier; *IsVolatile = VolatileQualifier;
@ -570,7 +577,7 @@ void TypeParseIdentPart(struct ParseState *Parser, struct ValueType *BasicTyp,
if (*Typ != NULL) if (*Typ != NULL)
ProgramFail(Parser, "bad type declaration"); ProgramFail(Parser, "bad type declaration");
TypeParse(Parser, Typ, Identifier, NULL, NULL); TypeParse(Parser, Typ, Identifier, NULL, NULL, NULL);
if (LexGetToken(Parser, NULL, true) != TokenCloseBracket) if (LexGetToken(Parser, NULL, true) != TokenCloseBracket)
ProgramFail(Parser, "')' expected"); ProgramFail(Parser, "')' expected");
break; break;
@ -606,11 +613,11 @@ void TypeParseIdentPart(struct ParseState *Parser, struct ValueType *BasicTyp,
/* parse a type - a complete declaration including identifier */ /* parse a type - a complete declaration including identifier */
void TypeParse(struct ParseState *Parser, struct ValueType **Typ, 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; struct ValueType *BasicType;
TypeParseFront(Parser, &BasicType, IsStatic, IsVolatile); TypeParseFront(Parser, &BasicType, IsStatic, IsExtern, IsVolatile);
TypeParseIdentPart(Parser, BasicType, Typ, Identifier); TypeParseIdentPart(Parser, BasicType, Typ, Identifier);
} }