Skip to content

Commit

Permalink
Added support for #include of predefined libraries.
Browse files Browse the repository at this point in the history
Created a stdio.h predefined library.
  • Loading branch information
zik.saleeba committed Jun 5, 2010
1 parent e572ba3 commit b782c1b
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 9 deletions.
4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ CFLAGS=-Wall -pedantic -g -DUNIX_HOST
LIBS=-lm

TARGET = picoc
SRCS = picoc.c table.c lex.c parse.c expression.c heap.c type.c variable.c clibrary.c library_unix.c platform.c platform_unix.c math_library.c
SRCS = picoc.c table.c lex.c parse.c expression.c heap.c type.c \
variable.c clibrary.c library_unix.c platform.c platform_unix.c \
math_library.c include.c library_stdio.c
OBJS := $(SRCS:%.c=%.o)

all: depend $(TARGET)
Expand Down
60 changes: 60 additions & 0 deletions include.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#include "picoc.h"

#ifndef NO_HASH_INCLUDE

/* a list of libraries we can include */
struct IncludeLibrary
{
const char *IncludeName;
void (*SetupFunction)(void);
struct LibraryFunction (*FuncList)[];
const char *SetupCSource;
};

struct IncludeLibrary IncludeLibInfo[] =
{
{ "stdio.h",
&StdioSetupFunc,
&StdioFunctions,
StdioDefs },
{ NULL, NULL, NULL, NULL }
};


/* include one of a number of predefined libraries, or perhaps an actual file */
void IncludeFile(char *FileName)
{
struct IncludeLibrary *LInclude;

/* scan for the include file name to see if it's in our list of predefined includes */
for (LInclude = &IncludeLibInfo[0]; LInclude->IncludeName != NULL; LInclude++)
{
if (strcmp(LInclude->IncludeName, FileName) == 0)
{
/* found it - protect against multiple inclusion */
if (!VariableDefined(FileName))
{
VariableDefine(NULL, FileName, NULL, &VoidType, FALSE);

/* parse the setup C source code - may define types etc. */
if (LInclude->SetupFunction != NULL)
(*LInclude->SetupFunction)();

/* parse the setup C source code - may define types etc. */
if (LInclude->SetupCSource != NULL)
Parse(FileName, LInclude->SetupCSource, strlen(LInclude->SetupCSource), TRUE);

/* set up the library functions */
if (LInclude->FuncList != NULL)
LibraryInit(&GlobalTable, FileName, LInclude->FuncList);
}

return;
}
}

/* not a predefined file, read a real file */
PlatformScanFile(FileName);
}

#endif /* NO_HASH_INCLUDE */
15 changes: 10 additions & 5 deletions lex.c
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,9 @@ enum LexToken LexGetWord(struct LexState *Lexer, struct Value *Value)
Value->Val->Identifier = TableStrRegister2(StartPos, Lexer->Pos - StartPos);

Token = LexCheckReservedWord(Value->Val->Identifier);
if (Token == TokenHashInclude)
Lexer->ScanningHashInclude = TRUE;

if (Token != TokenNone)
return Token;

Expand Down Expand Up @@ -270,7 +273,7 @@ unsigned char LexUnEscapeCharacter(const char **From, const char *End)
}

/* get a string constant - used while scanning */
enum LexToken LexGetStringConstant(struct LexState *Lexer, struct Value *Value)
enum LexToken LexGetStringConstant(struct LexState *Lexer, struct Value *Value, char EndChar)
{
int Escape = FALSE;
const char *StartPos = Lexer->Pos;
Expand All @@ -280,7 +283,7 @@ enum LexToken LexGetStringConstant(struct LexState *Lexer, struct Value *Value)
char *RegString;
struct Value *ArrayValue;

while (Lexer->Pos != Lexer->End && (*Lexer->Pos != '"' || Escape))
while (Lexer->Pos != Lexer->End && (*Lexer->Pos != EndChar || Escape))
{
/* find the end */
if (Escape)
Expand Down Expand Up @@ -315,7 +318,7 @@ enum LexToken LexGetStringConstant(struct LexState *Lexer, struct Value *Value)
/* create the the pointer for this char* */
Value->Typ = CharPtrType;
Value->Val->NativePointer = RegString;
if (*Lexer->Pos == '"')
if (*Lexer->Pos == EndChar)
LEXER_INC(Lexer);

return TokenStringConstant;
Expand Down Expand Up @@ -370,6 +373,7 @@ enum LexToken LexScanGetToken(struct LexState *Lexer, struct Value **Value)
{
Lexer->Line++;
Lexer->Pos++;
Lexer->ScanningHashInclude = FALSE;
#ifdef FANCY_ERROR_REPORTING
Lexer->CharacterPos = 0;
#endif
Expand All @@ -393,7 +397,7 @@ enum LexToken LexScanGetToken(struct LexState *Lexer, struct Value **Value)
LEXER_INC(Lexer);
switch (ThisChar)
{
case '"': GotToken = LexGetStringConstant(Lexer, *Value); break;
case '"': GotToken = LexGetStringConstant(Lexer, *Value, '"'); break;
case '\'': GotToken = LexGetCharacterConstant(Lexer, *Value); break;
case '(': GotToken = TokenOpenBracket; break;
case ')': GotToken = TokenCloseBracket; break;
Expand All @@ -403,7 +407,7 @@ enum LexToken LexScanGetToken(struct LexState *Lexer, struct Value **Value)
case '*': NEXTIS('=', TokenMultiplyAssign, TokenAsterisk); break;
case '/': if (NextChar == '/' || NextChar == '*') LexSkipComment(Lexer, NextChar); else NEXTIS('=', TokenDivideAssign, TokenSlash); break;
case '%': NEXTIS('=', TokenModulusAssign, TokenModulus); break;
case '<': NEXTIS3PLUS('=', TokenLessEqual, '<', TokenShiftLeft, '=', TokenShiftLeftAssign, TokenLessThan); break;
case '<': if (Lexer->ScanningHashInclude) GotToken = LexGetStringConstant(Lexer, *Value, '>'); else { NEXTIS3PLUS('=', TokenLessEqual, '<', TokenShiftLeft, '=', TokenShiftLeftAssign, TokenLessThan); } break;
case '>': NEXTIS3PLUS('=', TokenGreaterEqual, '>', TokenShiftRight, '=', TokenShiftRightAssign, TokenGreaterThan); break;
case ';': GotToken = TokenSemicolon; break;
case '&': NEXTIS3('=', TokenArithmeticAndAssign, '&', TokenLogicalAnd, TokenAmpersand); break;
Expand Down Expand Up @@ -524,6 +528,7 @@ void *LexAnalyse(const char *FileName, const char *Source, int SourceLen, int *T
Lexer.End = Source + SourceLen;
Lexer.Line = 1;
Lexer.FileName = FileName;
Lexer.ScanningHashInclude = FALSE;
#ifdef FANCY_ERROR_REPORTING
Lexer.CharacterPos = 1;
Lexer.SourceText = Source;
Expand Down
58 changes: 58 additions & 0 deletions library_stdio.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/* stdio.h library */
#include "picoc.h"

#ifndef NO_HASH_INCLUDE

void StdioFopen(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
ReturnValue->Val->NativePointer = fopen(Param[0]->Val->NativePointer, Param[1]->Val->NativePointer);
}

void StdioFclose(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
ReturnValue->Val->Integer = fclose(Param[0]->Val->NativePointer);
}

void StdioFread(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
ReturnValue->Val->Integer = fread(Param[0]->Val->NativePointer, Param[1]->Val->Integer, Param[2]->Val->Integer, Param[3]->Val->NativePointer);
}

void StdioFwrite(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
ReturnValue->Val->Integer = fwrite(Param[0]->Val->NativePointer, Param[1]->Val->Integer, Param[2]->Val->Integer, Param[3]->Val->NativePointer);
}

void StdioFgetc(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
ReturnValue->Val->Integer = fgetc(Param[0]->Val->NativePointer);
}

void StdioFgets(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
ReturnValue->Val->NativePointer = fgets(Param[0]->Val->NativePointer, Param[1]->Val->Integer, Param[2]->Val->NativePointer);
}

const char StdioDefs[] = "\
typedef struct FILEStruct FILE; \
";

struct LibraryFunction StdioFunctions[] =
{
{ StdioFopen, "FILE *fopen(char *, char *);" },
{ StdioFclose, "int fclose(FILE *);" },
{ StdioFread, "int fread(void *, int, int, FILE *);" },
{ StdioFwrite, "int fwrite(void *, int, int, FILE *);" },
{ StdioFgetc, "int fgetc(FILE *);" },
{ StdioFgetc, "int getc(FILE *);" },
{ StdioFgets, "char *fgets(char *, int, FILE *);" },
{ NULL, NULL }
};

void StdioSetupFunc(void)
{
/* make a "struct FILEStruct" which is the same size as a native FILE structure */
TypeCreateOpaqueStruct(NULL, TableStrRegister("FILEStruct"), sizeof(FILE));
}

#endif /* NO_HASH_INCLUDE */
6 changes: 4 additions & 2 deletions library_unix.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ void Ctest (struct ParseState *Parser, struct Value *ReturnValue, struct Value *
Param[0]->Val->Integer = 1234;
}

void Clineno (struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) {
void Clineno (struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
ReturnValue->Val->Integer = Parser->Line;
}

void Cerrormsg (struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) {
void Cerrormsg (struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
PlatformErrorPrefix(Parser);
LibPrintf(Parser, ReturnValue, Param, NumArgs);
}
Expand Down
2 changes: 1 addition & 1 deletion parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ enum ParseResult ParseStatement(struct ParseState *Parser, int CheckTrailingSemi
if (LexGetToken(Parser, &LexerValue, TRUE) != TokenStringConstant)
ProgramFail(Parser, "\"filename.h\" expected");

PlatformScanFile((char *)LexerValue->Val->NativePointer);
IncludeFile((char *)LexerValue->Val->NativePointer);
CheckTrailingSemicolon = FALSE;
break;
#endif
Expand Down
10 changes: 10 additions & 0 deletions picoc.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ struct LexState
const char *End;
const char *FileName;
int Line;
int ScanningHashInclude;
#ifdef FANCY_ERROR_REPORTING
int CharacterPos;
const char *SourceText;
Expand Down Expand Up @@ -338,6 +339,7 @@ int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ);
void TypeParseIdentPart(struct ParseState *Parser, struct ValueType *BasicTyp, struct ValueType **Typ, char **Identifier);
void TypeParse(struct ParseState *Parser, struct ValueType **Typ, 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);

/* heap.c */
void HeapInit();
Expand Down Expand Up @@ -398,4 +400,12 @@ void PlatformLibraryInit();
void Initialise();
void Cleanup();

/* include.c */
void IncludeFile(char *Filename);

/* library_stdio.c */
extern const char StdioDefs[];
extern struct LibraryFunction StdioFunctions[];
void StdioSetupFunc(void);

#endif /* PICOC_H */
14 changes: 14 additions & 0 deletions type.c
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,20 @@ void TypeParseStruct(struct ParseState *Parser, struct ValueType **Typ, int IsSt
LexGetToken(Parser, NULL, TRUE);
}

/* create a system struct which has no user-visible members */
struct ValueType *TypeCreateOpaqueStruct(struct ParseState *Parser, const char *StructName, int Size)
{
struct ValueType *Typ = TypeGetMatching(Parser, &UberType, TypeStruct, 0, StructName);

/* create the (empty) table */
Typ->Members = VariableAlloc(Parser, sizeof(struct Table) + STRUCT_TABLE_SIZE * sizeof(struct TableEntry), TRUE);
Typ->Members->HashTable = (struct TableEntry **)((char *)Typ->Members + sizeof(struct Table));
TableInitTable(Typ->Members, (struct TableEntry **)((char *)Typ->Members + sizeof(struct Table)), STRUCT_TABLE_SIZE, TRUE);
Typ->Sizeof = Size;

return Typ;
}

/* parse an enum declaration */
void TypeParseEnum(struct ParseState *Parser, struct ValueType **Typ)
{
Expand Down

0 comments on commit b782c1b

Please sign in to comment.