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:
parent
875a635648
commit
d04337125e
|
@ -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
9
c-tests/extern.c
Normal 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
4
c-tests/extern.h
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
extern int a;
|
||||||
|
extern long b;
|
||||||
|
|
||||||
|
//void decrement();
|
8
c-tests/extern2.c
Normal file
8
c-tests/extern2.c
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#include "extern.h"
|
||||||
|
|
||||||
|
long b = 1;
|
||||||
|
|
||||||
|
void decrement() {
|
||||||
|
a--;
|
||||||
|
b--;
|
||||||
|
}
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
10
parse.c
|
@ -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
17
type.c
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue