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 */
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);
}
```

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);
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);

View file

@ -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;

View file

@ -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,

10
parse.c
View file

@ -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;

17
type.c
View file

@ -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);
}