Big changes to string constants.

Got rid of str.c.
First attempt at stdarg params in printf()


git-svn-id: http://picoc.googlecode.com/svn/trunk@97 21eae674-98b7-11dd-bd71-f92a316d2d60
This commit is contained in:
zik.saleeba 2009-02-21 02:35:52 +00:00
parent 2ac131247b
commit 4821d689ad
11 changed files with 335 additions and 219 deletions

View file

@ -3,7 +3,7 @@ CFLAGS=-Wall -g #-DDEBUG_LEXER #-DDEBUG_HEAP -DDEBUG_LEXER
LIBS=-lm
TARGET = picoc
SRCS = picoc.c table.c lex.c parse.c intrinsic.c heap.c type.c variable.c str.c
SRCS = picoc.c table.c lex.c parse.c intrinsic.c heap.c type.c variable.c
OBJS := $(SRCS:%.c=%.o)
all: $(TARGET)

11
TODO
View file

@ -4,7 +4,18 @@ TODO
* operator precedence
* enum
* interactive mode
* casts
* change heap to use a single consistent freelist node struct
* periodic heap cleanup
* fix type comparison to take into account array size
* expression and auto-cast support for all types
* octal/hex character constants
* fix #include
* eliminate host printf/scanf use
Need test/debug:
* all break/continue variations
* #define
Also:
* Remove Var parameter from HeapPopStack() once we're certain it all works

View file

@ -1,42 +1,168 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "picoc.h"
void IntrinsicPrintInt(struct Value *ReturnValue, struct Value **Param)
/* print an integer to a stream without using printf/sprintf */
void IntrinsicPrintInt(int Num, FILE *Stream)
{
int Div;
int Remainder = 0;
int Printing = FALSE;
if (Num < 0)
{
fputc('-', Stream);
Num = -Num;
}
if (Num == 0)
fputc('0', Stream);
else
{
Div = LARGE_INT_POWER_OF_TEN;
while (Div > 0)
{
Remainder = Num / Div;
if (Printing || Remainder > 0)
{
fputc('0' + Remainder, Stream);
Printing = TRUE;
}
Num -= Remainder * Div;
Div /= 10;
}
}
}
/* print a double to a stream without using printf/sprintf */
void IntrinsicPrintFP(double Num, FILE *Stream)
{
int Exponent = 0;
if (abs(Num) >= 1e7)
Exponent = log(Num) / LOG10E;
else if (abs(Num) <= 1e-7)
Exponent = log(Num) / LOG10E - 0.999999999;
Num /= pow(10.0, Exponent);
IntrinsicPrintInt((int)Num, Stream);
fputc('.', Stream);
for (Num -= (int)Num; Num != 0.0; Num *= 10.0)
fputc('0' + (int)Num, Stream);
if (Exponent)
{
fputc('e', Stream);
IntrinsicPrintInt(Exponent, Stream);
}
}
/* intrinsic functions made available to the language */
void IntrinsicPrintInteger(struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
printf("%d\n", Param[0]->Val->Integer);
}
void IntrinsicPrintf(struct Value *ReturnValue, struct Value **Param)
void IntrinsicPrintf(struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
printf("IntrinsicPrintf\n");
struct Value *CharArray = Param[0]->Val->Pointer.Segment;
char *Format;
char *FPos;
struct Value *NextArg = Param[0];
struct ValueType *FormatType;
int ArgCount = 1;
if (Param[0]->Val->Pointer.Data.Offset < 0 || Param[0]->Val->Pointer.Data.Offset >= CharArray->Val->Array.Size)
Format = StrEmpty;
else
Format = CharArray->Val->Array.Data + Param[0]->Val->Pointer.Data.Offset;
for (FPos = Format; *FPos != '\0'; FPos++)
{
if (*FPos == '%')
{
FPos++;
switch (*FPos)
{
case 's': FormatType = CharPtrType; break;
case 'd': FormatType = &IntType; break;
case 'c': FormatType = &CharType; break;
case 'f': FormatType = &FPType; break;
case '%': fputc('%', stdout); FormatType = NULL; break;
case '\0': FPos--; FormatType = NULL; break;
default: putchar(*FPos); FormatType = NULL; break;
}
if (FormatType != NULL)
{ /* we have to format something */
if (ArgCount >= NumArgs)
fputs("XXX", stdout); /* not enough parameters for format */
else
{
NextArg = (struct Value *)((void *)NextArg + sizeof(struct Value) + TypeSizeValue(NextArg));
if (NextArg->Typ != FormatType)
fputs("XXX", stdout); /* bad type for format */
else
{
switch (*FPos)
{
case 's':
{
struct Value *CharArray = NextArg->Val->Pointer.Segment;
char *Str;
if (NextArg->Val->Pointer.Data.Offset < 0 || NextArg->Val->Pointer.Data.Offset >= CharArray->Val->Array.Size)
Str = StrEmpty;
else
Str = CharArray->Val->Array.Data + NextArg->Val->Pointer.Data.Offset;
fputs(Str, stdout);
break;
}
case 'd': IntrinsicPrintInt(NextArg->Val->Integer, stdout); break;
case 'c': fputc(NextArg->Val->Integer, stdout); break;
case 'f': IntrinsicPrintFP(NextArg->Val->FP, stdout); break;
}
}
}
ArgCount++;
}
}
else
putchar(*FPos);
}
}
void IntrinsicSayHello(struct Value *ReturnValue, struct Value **Param)
void IntrinsicSayHello(struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
printf("Hello\n");
}
struct IntrinsicFunction
{
void (*Func)(struct Value *, struct Value **);
void (*Func)(struct Value *, struct Value **, int);
const char *Prototype;
} Intrinsics[] =
{
{ IntrinsicSayHello, "void sayhello()" },
{ IntrinsicPrintf, "void printf(char *, ...)" },
{ IntrinsicPrintInt, "void printint(int)" },
{ IntrinsicPrintInteger,"void printint(int)" },
};
void IntrinsicInit(struct Table *GlobalTable)
{
struct ParseState Parser;
int Count;
const char *Identifier;
char *Identifier;
struct ValueType *ReturnType;
struct Value *NewValue;
void *Tokens;
const char *IntrinsicName = StrRegister("intrinsic");
const char *IntrinsicName = TableStrRegister("intrinsic");
for (Count = 0; Count < sizeof(Intrinsics) / sizeof(struct IntrinsicFunction); Count++)
{
@ -48,3 +174,39 @@ void IntrinsicInit(struct Table *GlobalTable)
HeapFree(Tokens);
}
}
#if 0
void IntrinsicHostPrintf(const char *Format, ...)
{
va_list Args;
va_start(Args, Format);
vStrPrintf(Format, Args);
va_end(Args);
}
#endif
/* printf for compiler error reporting */
void IntrinsicHostVPrintf(const char *Format, va_list Args)
{
const char *FPos;
for (FPos = Format; *FPos != '\0'; FPos++)
{
if (*FPos == '%')
{
FPos++;
switch (*FPos)
{
case 's': fputs(va_arg(Args, char *), stdout); break;
case 'd': IntrinsicPrintInt(va_arg(Args, int), stdout); break;
case 'c': fputc(va_arg(Args, int), stdout); break;
case 'f': IntrinsicPrintFP(va_arg(Args, double), stdout); break;
case '%': fputc('%', stdout); break;
case '\0': FPos--; break;
}
}
else
putchar(*FPos);
}
}

45
lex.c
View file

@ -56,14 +56,6 @@ static struct ReservedWord ReservedWords[] =
{ "while", TokenWhile, NULL }
};
struct LexState
{
const char *Pos;
const char *End;
int Line;
const char *FileName;
};
/* initialise the lexer */
void LexInit()
@ -71,19 +63,7 @@ void LexInit()
int Count;
for (Count = 0; Count < sizeof(ReservedWords) / sizeof(struct ReservedWord); Count++)
ReservedWords[Count].SharedWord = StrRegister(ReservedWords[Count].Word);
}
/* exit with a message */
void LexFail(struct LexState *Lexer, const char *Message, ...)
{
va_list Args;
printf("%s:%d: ", Lexer->FileName, Lexer->Line);
va_start(Args, Message);
vprintf(Message, Args);
printf("\n");
exit(1);
ReservedWords[Count].SharedWord = TableStrRegister(ReservedWords[Count].Word);
}
/* check if a word is a reserved word - used while scanning */
@ -141,11 +121,11 @@ enum LexToken LexGetWord(struct LexState *Lexer, struct Value *Value)
while (Lexer->Pos != Lexer->End && isCident(*Pos))
Pos++;
Value->Typ = &StringType;
Value->Val->String = (char *)StrRegister2(Lexer->Pos, Pos - Lexer->Pos);
Value->Typ = NULL;
Value->Val->Identifier = TableStrRegister2(Lexer->Pos, Pos - Lexer->Pos);
Lexer->Pos = Pos;
Token = LexCheckReservedWord(Value->Val->String);
Token = LexCheckReservedWord(Value->Val->Identifier);
if (Token != TokenNone)
return Token;
@ -200,8 +180,8 @@ enum LexToken LexGetStringConstant(struct LexState *Lexer, struct Value *Value)
const char *EndPos;
char *EscBuf;
char *EscBufPos;
struct Value *ArrayValue;
Value->Typ = &StringType;
while (Lexer->Pos != Lexer->End && (*Lexer->Pos != '"' || Escape))
{ /* find the end */
if (Escape)
@ -214,11 +194,21 @@ enum LexToken LexGetStringConstant(struct LexState *Lexer, struct Value *Value)
EndPos = Lexer->Pos;
EscBuf = HeapAllocStack(EndPos - StartPos);
if (EscBuf == NULL)
LexFail(Lexer, "out of memory");
for (EscBufPos = EscBuf, Lexer->Pos = StartPos; Lexer->Pos != EndPos;)
*EscBufPos++ = LexUnEscapeCharacter(&Lexer->Pos, EndPos);
Value->Val->String = (char *)StrRegister2(EscBuf, EscBufPos - EscBuf);
ArrayValue = VariableAllocValueAndData(NULL, sizeof(struct ArrayValue), FALSE, TRUE);
ArrayValue->Typ = CharArrayType;
ArrayValue->Val->Array.Size = EscBufPos - EscBuf + 1;
ArrayValue->Val->Array.Data = TableStrRegister2(EscBuf, EscBufPos - EscBuf);
HeapPopStack(EscBuf, EndPos - StartPos);
Value->Typ = CharPtrType;
Value->Val->Pointer.Segment = ArrayValue;
Value->Val->Pointer.Data.Offset = 0;
if (*Lexer->Pos == '"')
Lexer->Pos++;
@ -441,7 +431,8 @@ enum LexToken LexGetToken(struct ParseState *Parser, struct Value **Value, int I
{
switch (Token)
{
case TokenStringConstant: case TokenIdentifier: LexValue.Typ = &StringType; break;
case TokenStringConstant: LexValue.Typ = CharPtrType; break;
case TokenIdentifier: LexValue.Typ = NULL; break;
case TokenIntegerConstant: LexValue.Typ = &IntType; break;
case TokenCharacterConstant: LexValue.Typ = &CharType; break;
case TokenFPConstant: LexValue.Typ = &FPType; break;

30
parse.c
View file

@ -12,8 +12,8 @@ int ParseStatementMaybeRun(struct ParseState *Parser, int Condition);
void ParseInit()
{
VariableInit();
IntrinsicInit(&GlobalTable);
TypeInit();
IntrinsicInit(&GlobalTable);
}
/* do a function call */
@ -34,6 +34,8 @@ void ParseFunctionCall(struct ParseState *Parser, struct Value **Result, const c
*Result = VariableAllocValueFromType(Parser, FuncValue->Val->FuncDef.ReturnType, FALSE);
HeapPushStackFrame();
ParamArray = HeapAllocStack(sizeof(struct Value *) * FuncValue->Val->FuncDef.NumParams);
if (ParamArray == NULL)
ProgramFail(Parser, "out of memory");
}
/* parse arguments */
@ -162,12 +164,12 @@ int ParseValue(struct ParseState *Parser, struct Value **Result)
case TokenIdentifier:
if (LexGetToken(Parser, NULL, FALSE) == TokenOpenBracket)
ParseFunctionCall(Parser, Result, LexValue->Val->String);
ParseFunctionCall(Parser, Result, LexValue->Val->Identifier);
else
{
if (Parser->Mode == RunModeRun)
{
VariableGet(Parser, LexValue->Val->String, &LocalLValue);
VariableGet(Parser, LexValue->Val->Identifier, &LocalLValue);
if (LocalLValue->Typ->Base == TypeMacro)
{
struct ParseState MacroLexer = LocalLValue->Val->Parser;
@ -211,11 +213,11 @@ int ParseValue(struct ParseState *Parser, struct Value **Result)
if ((*Result)->Typ->Base != TypeArray)
ProgramFail(Parser, "not an array");
if (IntValue < 0 || IntValue >= (*Result)->Typ->ArraySize)
if (IntValue < 0 || IntValue >= (*Result)->Val->Array.Size)
ProgramFail(Parser, "illegal array index");
VariableStackPop(Parser, *Result);
*Result = VariableAllocValueFromExistingData(Parser, (*Result)->Typ->FromType, (union AnyValue *)((void *)(*Result)->Val + (*Result)->Typ->FromType->Sizeof * IntValue), TRUE);
*Result = VariableAllocValueFromExistingData(Parser, (*Result)->Typ->FromType, (union AnyValue *)((void *)(*Result)->Val + TypeSize((*Result)->Typ->FromType, 0)), TRUE);
}
}
}
@ -281,8 +283,8 @@ int ParseExpression(struct ParseState *Parser, struct Value **Result)
if (TotalValue->Typ->Base != TypeStruct && TotalValue->Typ->Base != TypeUnion)
ProgramFail(Parser, "can't use '.' on something that's not a struct or union");
if (!TableGet(TotalValue->Typ->Members, Ident->Val->String, &CurrentValue))
ProgramFail(Parser, "structure doesn't have a member called '%s'", Ident->Val->String);
if (!TableGet(TotalValue->Typ->Members, Ident->Val->Identifier, &CurrentValue))
ProgramFail(Parser, "structure doesn't have a member called '%s'", Ident->Val->Identifier);
VariableStackPop(Parser, TotalValue);
TotalValue = VariableAllocValueFromExistingData(Parser, CurrentValue->Typ, TotalValueData + CurrentValue->Val->Integer, TRUE);
@ -423,10 +425,10 @@ int ParseIntExpression(struct ParseState *Parser)
}
/* parse a function definition and store it for later */
struct Value *ParseFunctionDefinition(struct ParseState *Parser, struct ValueType *ReturnType, const char *Identifier, int IsPrototype)
struct Value *ParseFunctionDefinition(struct ParseState *Parser, struct ValueType *ReturnType, char *Identifier, int IsPrototype)
{
struct ValueType *ParamType;
const char *ParamIdentifier;
char *ParamIdentifier;
enum LexToken Token;
struct Value *FuncValue;
struct ParseState ParamParser;
@ -503,8 +505,8 @@ void ParseMacroDefinition(struct ParseState *Parser)
MacroValue->Val->Parser = *Parser;
MacroValue->Typ = &MacroType;
if (!TableSet(&GlobalTable, MacroName->Val->String, MacroValue))
ProgramFail(Parser, "'%s' is already defined", &MacroName->Val->String);
if (!TableSet(&GlobalTable, MacroName->Val->Identifier, MacroValue))
ProgramFail(Parser, "'%s' is already defined", &MacroName->Val->Identifier);
}
/* copy where we're at in the parsing */
@ -624,7 +626,7 @@ int ParseStatement(struct ParseState *Parser)
struct Value *CValue;
int Condition;
struct ParseState PreState = *Parser;
const char *Identifier;
char *Identifier;
struct ValueType *Typ;
enum LexToken Token = LexGetToken(Parser, NULL, TRUE);
@ -747,7 +749,7 @@ int ParseStatement(struct ParseState *Parser)
if (LexGetToken(Parser, &LexerValue, TRUE) != TokenStringConstant)
ProgramFail(Parser, "\"filename.h\" expected");
ScanFile(LexerValue->Val->String);
//ScanFile(LexerValue->Val->String); // XXX - need to dereference char * here
break;
}
@ -821,7 +823,7 @@ int ParseStatement(struct ParseState *Parser)
ProgramFail(Parser, "wrong return type");
// XXX - make assignment a separate function
memcpy(TopStackFrame->ReturnValue->Val, CValue->Val, TopStackFrame->ReturnValue->Typ->Sizeof);
memcpy(TopStackFrame->ReturnValue->Val, CValue->Val, TypeSizeValue(CValue));
Parser->Mode = RunModeReturn;
}
break;

18
picoc.c
View file

@ -23,6 +23,18 @@ void ProgramFail(struct ParseState *Parser, const char *Message, ...)
exit(1);
}
/* exit with a message */
void LexFail(struct LexState *Lexer, const char *Message, ...)
{
va_list Args;
printf("%s:%d: ", Lexer->FileName, Lexer->Line);
va_start(Args, Message);
vprintf(Message, Args);
printf("\n");
exit(1);
}
/* read a file into memory */
char *ReadFile(const char *FileName)
{
@ -33,7 +45,7 @@ char *ReadFile(const char *FileName)
if (stat(FileName, &FileInfo))
ProgramFail(NULL, "can't read file %s\n", FileName);
ReadText = HeapAlloc(FileInfo.st_size + 1);
ReadText = malloc(FileInfo.st_size + 1);
if (ReadText == NULL)
ProgramFail(NULL, "out of memory\n");
@ -55,7 +67,7 @@ void ScanFile(const char *FileName)
{
char *SourceStr = ReadFile(FileName);
Parse(FileName, SourceStr, strlen(SourceStr), TRUE);
HeapFree(SourceStr);
free(SourceStr);
}
int main(int argc, char **argv)
@ -64,7 +76,7 @@ int main(int argc, char **argv)
ProgramFail(NULL, "Format: picoc <program.c> <args>...\n");
HeapInit();
StrInit();
TableInit();
VariableInit();
LexInit();
ParseInit();

50
picoc.h
View file

@ -4,7 +4,7 @@
#include <stdarg.h>
/* configurable options */
#define HEAP_SIZE 8192 /* space for the heap and the stack */
#define HEAP_SIZE 16384 /* space for the heap and the stack */
#define LARGE_INT_POWER_OF_TEN 1000000000 /* the largest power of ten which fits in an int on this architecture */
#define ARCH_ALIGN_WORDSIZE sizeof(int) /* memory alignment boundary on this architecture */
@ -37,8 +37,6 @@
#define PATH_MAX 1024
#endif
#define ISVALUETYPE(t) (((t)->Base == TypeInt) || ((t)->Base == TypeFP) || ((t)->Base == TypeString))
struct Table;
/* lexical tokens */
@ -97,7 +95,6 @@ enum BaseType
TypeInt, /* integer */
TypeFP, /* floating point */
TypeChar, /* a single character - acts like an integer except in machine memory access */
TypeString, /* a constant source text string with C string emulation */
TypeFunction, /* a function */
TypeMacro, /* a macro */
TypePointer, /* a pointer */
@ -154,7 +151,7 @@ union AnyValue
short ShortInteger;
int Integer;
double FP;
char *String;
char *Identifier;
struct ArrayValue Array;
struct PointerValue Pointer;
struct ParseState Parser;
@ -179,11 +176,11 @@ struct TableEntry
{
struct ValueEntry
{
const char *Key; /* points to the shared string table */
char *Key; /* points to the shared string table */
struct Value *Val; /* the value we're storing */
} v; /* used for tables of values */
const char Key[1]; /* dummy size - used for the shared string table */
char Key[1]; /* dummy size - used for the shared string table */
} p;
};
@ -206,27 +203,41 @@ struct StackFrame
struct StackFrame *PreviousStackFrame; /* the next lower stack frame */
};
/* lexer state */
struct LexState
{
const char *Pos;
const char *End;
int Line;
const char *FileName;
};
/* globals */
extern struct Table GlobalTable;
extern struct StackFrame *TopStackFrame;
extern struct ValueType IntType;
extern struct ValueType CharType;
extern struct ValueType StringType;
extern struct ValueType FPType;
extern struct ValueType VoidType;
extern struct ValueType FunctionType;
extern struct ValueType MacroType;
extern const char *StrEmpty;
extern struct ValueType *CharPtrType;
extern struct ValueType *CharArrayType;
extern char *StrEmpty;
/* picoc.c */
void ProgramFail(struct ParseState *Parser, const char *Message, ...);
void LexFail(struct LexState *Lexer, const char *Message, ...);
void ScanFile(const char *FileName);
/* table.c */
void TableInit(struct Table *Tbl, struct TableEntry **HashTable, int Size, int OnHeap);
int TableSet(struct Table *Tbl, const char *Key, struct Value *Val);
void TableInit();
char *TableStrRegister(const char *Str);
char *TableStrRegister2(const char *Str, int Len);
void TableInitTable(struct Table *Tbl, struct TableEntry **HashTable, int Size, int OnHeap);
int TableSet(struct Table *Tbl, char *Key, struct Value *Val);
int TableGet(struct Table *Tbl, const char *Key, struct Value **Val);
const char *TableSetIdentifier(struct Table *Tbl, const char *Ident, int IdentLen);
char *TableSetIdentifier(struct Table *Tbl, const char *Ident, int IdentLen);
/* lex.c */
void LexInit(void);
@ -239,17 +250,19 @@ void ParseInit(void);
int ParseExpression(struct ParseState *Parser, struct Value **Result);
int ParseIntExpression(struct ParseState *Parser);
int ParseStatement(struct ParseState *Parser);
struct Value *ParseFunctionDefinition(struct ParseState *Parser, struct ValueType *ReturnType, const char *Identifier, int IsProtoType);
struct Value *ParseFunctionDefinition(struct ParseState *Parser, struct ValueType *ReturnType, char *Identifier, int IsProtoType);
void Parse(const char *FileName, const char *Source, int SourceLen, int RunIt);
/* type.c */
void TypeInit();
int TypeSizeof(struct ValueType *Typ);
void TypeParse(struct ParseState *Parser, struct ValueType **Typ, const char **Identifier);
int TypeSize(struct ValueType *Typ, int ArraySize);
int TypeSizeValue(struct Value *Val);
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);
/* intrinsic.c */
void IntrinsicInit(struct Table *GlobalTable);
void IntrinsicHostVPrintf(const char *Format, va_list Args);
/* heap.c */
void HeapInit();
@ -269,15 +282,10 @@ struct Value *VariableAllocValueAndCopy(struct ParseState *Parser, struct Value
struct Value *VariableAllocValueFromType(struct ParseState *Parser, struct ValueType *Typ, int IsLValue);
struct Value *VariableAllocValueFromExistingData(struct ParseState *Parser, struct ValueType *Typ, union AnyValue *FromValue, int IsLValue);
struct Value *VariableAllocValueShared(struct ParseState *Parser, struct Value *FromValue);
void VariableDefine(struct ParseState *Parser, const char *Ident, struct Value *InitValue);
void VariableDefine(struct ParseState *Parser, char *Ident, struct Value *InitValue);
int VariableDefined(const char *Ident);
void VariableGet(struct ParseState *Parser, const char *Ident, struct Value **LVal);
void VariableStackFrameAdd(struct ParseState *Parser, int NumParams);
void VariableStackFramePop(struct ParseState *Parser);
/* str.c */
void StrInit();
const char *StrRegister(const char *Str);
const char *StrRegister2(const char *Str, int Len);
#endif /* PICOC_H */

123
str.c
View file

@ -1,123 +0,0 @@
/* maintains a shared string table so we don't have to worry about string allocation */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <math.h>
#include "picoc.h"
struct Table StringTable;
struct TableEntry *StringHashTable[STRING_TABLE_SIZE];
const char *StrEmpty = NULL;
/* initialise the shared string system */
void StrInit()
{
TableInit(&StringTable, &StringHashTable[0], STRING_TABLE_SIZE, TRUE);
StrEmpty = StrRegister("");
}
/* register a string in the shared string store */
const char *StrRegister2(const char *Str, int Len)
{
return TableSetIdentifier(&StringTable, Str, Len);
}
const char *StrRegister(const char *Str)
{
return StrRegister2(Str, strlen(Str));
}
/* print an integer to a stream without using printf/sprintf */
void StrPrintInt(int Num, FILE *Stream)
{
int Div;
int Remainder = 0;
int Printing = FALSE;
if (Num < 0)
{
fputc('-', Stream);
Num = -Num;
}
if (Num == 0)
fputc('0', Stream);
else
{
Div = LARGE_INT_POWER_OF_TEN;
while (Div > 0)
{
Remainder = Num / Div;
if (Printing || Remainder > 0)
{
fputc('0' + Remainder, Stream);
Printing = TRUE;
}
Num -= Remainder * Div;
Div /= 10;
}
}
}
/* print a double to a stream without using printf/sprintf */
void StrPrintFP(double Num, FILE *Stream)
{
int Exponent = 0;
if (abs(Num) >= 1e7)
Exponent = log(Num) / LOG10E;
else if (abs(Num) <= 1e-7)
Exponent = log(Num) / LOG10E - 0.999999999;
Num /= pow(10.0, Exponent);
StrPrintInt((int)Num, Stream);
fputc('.', Stream);
for (Num -= (int)Num; Num != 0.0; Num *= 10.0)
fputc('0' + (int)Num, Stream);
if (Exponent)
{
fputc('e', Stream);
StrPrintInt(Exponent, Stream);
}
}
#if 0
/* Str version of printf */
void StrPrintf(const char *Format, ...)
{
va_list Args;
va_start(Args, Format);
vStrPrintf(Format, Args);
va_end(Args);
}
void vStrPrintf(const char *Format, va_list Args)
{
Str *str;
const char *FPos;
for (FPos = Format; *FPos != '\0'; FPos++)
{
if (*FPos == '%')
{
FPos++;
switch (*FPos)
{
case 'S': str = va_arg(Args, Str *); fwrite(str->Str, 1, str->Len, stdout); break;
case 's': fputs(va_arg(Args, char *), stdout); break;
case 'd': StrPrintInt(va_arg(Args, int), stdout); break;
case 'c': fputc(va_arg(Args, int), stdout); break;
case 'f': StrPrintFP(va_arg(Args, double), stdout); break;
case '%': fputc('%', stdout); break;
case '\0': FPos--; break;
}
}
else
putchar(*FPos);
}
}
#endif

35
table.c
View file

@ -1,6 +1,17 @@
#include <string.h>
#include "picoc.h"
struct Table StringTable;
struct TableEntry *StringHashTable[STRING_TABLE_SIZE];
char *StrEmpty = NULL;
/* initialise the shared string system */
void TableInit()
{
TableInit(&StringTable, &StringHashTable[0], STRING_TABLE_SIZE, TRUE);
StrEmpty = TableStrRegister("");
}
/* hash function for strings */
static unsigned int TableHash(const char *Key, int Len)
{
@ -20,7 +31,7 @@ static unsigned int TableHash(const char *Key, int Len)
}
/* initialise a table */
void TableInit(struct Table *Tbl, struct TableEntry **HashTable, int Size, int OnHeap)
void TableInitTable(struct Table *Tbl, struct TableEntry **HashTable, int Size, int OnHeap)
{
Tbl->Size = Size;
Tbl->OnHeap = OnHeap;
@ -45,8 +56,8 @@ static int TableSearch(struct Table *Tbl, const char *Key, int *AddAt)
}
/* set an identifier to a value. returns FALSE if it already exists.
* Key must be a shared string from StrRegister() */
int TableSet(struct Table *Tbl, const char *Key, struct Value *Val)
* Key must be a shared string from TableStrRegister() */
int TableSet(struct Table *Tbl, char *Key, struct Value *Val)
{
int AddAt;
int HashPos = TableSearch(Tbl, Key, &AddAt);
@ -65,7 +76,7 @@ int TableSet(struct Table *Tbl, const char *Key, struct Value *Val)
}
/* find a value in a table. returns FALSE if not found.
* Key must be a shared string from StrRegister() */
* Key must be a shared string from TableStrRegister() */
int TableGet(struct Table *Tbl, const char *Key, struct Value **Val)
{
int AddAt;
@ -94,7 +105,7 @@ static int TableSearchIdentifier(struct Table *Tbl, const char *Key, int Len, in
}
/* set an identifier and return the identifier. share if possible */
const char *TableSetIdentifier(struct Table *Tbl, const char *Ident, int IdentLen)
char *TableSetIdentifier(struct Table *Tbl, const char *Ident, int IdentLen)
{
int AddAt;
int HashPos = TableSearchIdentifier(Tbl, Ident, IdentLen, &AddAt);
@ -104,9 +115,23 @@ const char *TableSetIdentifier(struct Table *Tbl, const char *Ident, int IdentLe
else
{ /* add it to the table - we economise by not allocating the whole structure here */
struct TableEntry *NewEntry = HeapAlloc(sizeof(struct TableEntry *) + IdentLen + 1);
if (NewEntry == NULL)
ProgramFail(NULL, "out of memory");
strncpy((char *)&NewEntry->p.Key[0], Ident, IdentLen);
NewEntry->Next = Tbl->HashTable[AddAt];
Tbl->HashTable[AddAt] = NewEntry;
return &NewEntry->p.Key[0];
}
}
/* register a string in the shared string store */
char *TableStrRegister2(const char *Str, int Len)
{
return TableSetIdentifier(&StringTable, Str, Len);
}
char *TableStrRegister(const char *Str)
{
return TableStrRegister2(Str, strlen(Str));
}

39
type.c
View file

@ -4,13 +4,15 @@
struct ValueType UberType;
struct ValueType IntType;
struct ValueType CharType;
struct ValueType StringType;
struct ValueType WordType;
struct ValueType FPType;
struct ValueType VoidType;
struct ValueType FunctionType;
struct ValueType MacroType;
struct ValueType EnumType;
struct ValueType Type_Type;
struct ValueType *CharPtrType;
struct ValueType *CharArrayType;
/* add a new type to the set of types we know about */
@ -52,6 +54,24 @@ struct ValueType *TypeGetMatching(struct ParseState *Parser, struct ValueType *P
return TypeAdd(Parser, ParentType, Base, ArraySize, Identifier, Sizeof);
}
/* memory used by a value */
int TypeSizeValue(struct Value *Val)
{
if (Val->Typ->Base != TypeArray)
return Val->Typ->Sizeof;
else
return Val->Typ->FromType->Sizeof * Val->Val->Array.Size;
}
/* memory used by a variable given its type and array size */
int TypeSize(struct ValueType *Typ, int ArraySize)
{
if (Typ->Base != TypeArray)
return Typ->Sizeof;
else
return Typ->FromType->Sizeof * ArraySize;
}
/* add a base type */
void TypeAddBaseType(struct ValueType *TypeNode, enum BaseType Base, int Sizeof)
{
@ -71,13 +91,14 @@ void TypeInit()
{
UberType.DerivedTypeList = NULL;
TypeAddBaseType(&IntType, TypeInt, sizeof(int));
TypeAddBaseType(&CharType, TypeChar, sizeof(char));
TypeAddBaseType(&StringType, TypeString, sizeof(const char *));
TypeAddBaseType(&FPType, TypeFP, sizeof(double));
TypeAddBaseType(&VoidType, TypeVoid, 0);
TypeAddBaseType(&FunctionType, TypeFunction, sizeof(int));
TypeAddBaseType(&MacroType, TypeMacro, sizeof(int));
TypeAddBaseType(&Type_Type, TypeType, sizeof(struct ValueType *));
TypeAddBaseType(&CharType, TypeChar, sizeof(char));
CharPtrType = TypeAdd(NULL, &CharType, TypePointer, 0, StrEmpty, sizeof(char));
CharArrayType = TypeAdd(NULL, &CharType, TypeArray, 0, StrEmpty, sizeof(char));
}
/* parse a struct or union declaration */
@ -85,7 +106,7 @@ void TypeParseStruct(struct ParseState *Parser, struct ValueType **Typ, int IsSt
{
struct Value *LexValue;
struct ValueType *MemberType;
const char *MemberIdentifier;
char *MemberIdentifier;
struct Value *MemberValue;
enum LexToken Token;
@ -95,13 +116,13 @@ void TypeParseStruct(struct ParseState *Parser, struct ValueType **Typ, int IsSt
if (LexGetToken(Parser, &LexValue, TRUE) != TokenIdentifier)
ProgramFail(Parser, "struct/union name required");
*Typ = TypeGetMatching(Parser, &UberType, IsStruct ? TypeStruct : TypeUnion, 0, LexValue->Val->String);
*Typ = TypeGetMatching(Parser, &UberType, IsStruct ? TypeStruct : TypeUnion, 0, LexValue->Val->Identifier);
Token = LexGetToken(Parser, NULL, FALSE);
if (Token != TokenLeftBrace)
{ /* use the already defined structure */
if ((*Typ)->Members == NULL)
ProgramFail(Parser, "structure '%s' isn't defined", LexValue->Val->String);
ProgramFail(Parser, "structure '%s' isn't defined", LexValue->Val->Identifier);
return;
}
@ -109,7 +130,7 @@ void TypeParseStruct(struct ParseState *Parser, struct ValueType **Typ, int IsSt
LexGetToken(Parser, NULL, TRUE);
(*Typ)->Members = VariableAlloc(Parser, sizeof(struct Table) + STRUCT_TABLE_SIZE * sizeof(struct TableEntry), TRUE);
(*Typ)->Members->HashTable = (void *)(*Typ)->Members + sizeof(struct Table);
TableInit((*Typ)->Members, (void *)(*Typ)->Members + sizeof(struct Table), STRUCT_TABLE_SIZE, TRUE);
TableInitTable((*Typ)->Members, (void *)(*Typ)->Members + sizeof(struct Table), STRUCT_TABLE_SIZE, TRUE);
do {
TypeParse(Parser, &MemberType, &MemberIdentifier);
@ -142,7 +163,7 @@ void TypeParseStruct(struct ParseState *Parser, struct ValueType **Typ, int IsSt
}
/* parse a type */
void TypeParse(struct ParseState *Parser, struct ValueType **Typ, const char **Identifier)
void TypeParse(struct ParseState *Parser, struct ValueType **Typ, char **Identifier)
{
struct ParseState Before;
enum LexToken Token;
@ -189,7 +210,7 @@ void TypeParse(struct ParseState *Parser, struct ValueType **Typ, const char **I
if (*Typ == NULL || *Identifier != StrEmpty)
ProgramFail(Parser, "bad type declaration");
*Identifier = LexValue->Val->String;
*Identifier = LexValue->Val->Identifier;
Done = TRUE;
break;

View file

@ -2,6 +2,7 @@
#include <stdio.h>
#endif
#include <string.h>
#include <assert.h>
#include "picoc.h"
@ -16,7 +17,7 @@ struct StackFrame *TopStackFrame = NULL;
/* initialise the variable system */
void VariableInit()
{
TableInit(&GlobalTable, &GlobalHashTable[0], GLOBAL_TABLE_SIZE, TRUE);
TableInitTable(&GlobalTable, &GlobalHashTable[0], GLOBAL_TABLE_SIZE, TRUE);
TopStackFrame = NULL;
}
@ -56,7 +57,9 @@ struct Value *VariableAllocValueAndData(struct ParseState *Parser, int DataSize,
/* allocate a value given its type */
struct Value *VariableAllocValueFromType(struct ParseState *Parser, struct ValueType *Typ, int IsLValue)
{
struct Value *NewValue = VariableAllocValueAndData(Parser, Typ->Sizeof, IsLValue, FALSE);
int Size = TypeSize(Typ, Typ->ArraySize);
struct Value *NewValue = VariableAllocValueAndData(Parser, Size, IsLValue, FALSE);
assert(Size > 0 || Typ == &VoidType);
NewValue->Typ = Typ;
return NewValue;
}
@ -64,9 +67,10 @@ struct Value *VariableAllocValueFromType(struct ParseState *Parser, struct Value
/* allocate a value either on the heap or the stack and copy its value */
struct Value *VariableAllocValueAndCopy(struct ParseState *Parser, struct Value *FromValue, int OnHeap)
{
struct Value *NewValue = VariableAllocValueAndData(Parser, FromValue->Typ->Sizeof, FromValue->IsLValue, OnHeap);
int CopySize = TypeSizeValue(FromValue);
struct Value *NewValue = VariableAllocValueAndData(Parser, CopySize, FromValue->IsLValue, OnHeap);
NewValue->Typ = FromValue->Typ;
memcpy(NewValue->Val, FromValue->Val, FromValue->Typ->Sizeof);
memcpy(NewValue->Val, FromValue->Val, CopySize);
return NewValue;
}
@ -90,7 +94,7 @@ struct Value *VariableAllocValueShared(struct ParseState *Parser, struct Value *
}
/* define a variable */
void VariableDefine(struct ParseState *Parser, const char *Ident, struct Value *InitValue)
void VariableDefine(struct ParseState *Parser, char *Ident, struct Value *InitValue)
{
if (!TableSet((TopStackFrame == NULL) ? &GlobalTable : &TopStackFrame->LocalTable, Ident, VariableAllocValueAndCopy(Parser, InitValue, TopStackFrame == NULL)))
ProgramFail(Parser, "'%s' is already defined", Ident);
@ -127,7 +131,7 @@ void VariableStackPop(struct ParseState *Parser, struct Value *Var)
#ifdef DEBUG_HEAP
if (Var->ValOnStack)
printf("popping %d at 0x%lx\n", sizeof(struct Value) + Var->Typ->Sizeof, (unsigned long)Var);
printf("popping %d at 0x%lx\n", sizeof(struct Value) + VariableSizeValue(Var), (unsigned long)Var);
#endif
if (Var->ValOnHeap)
@ -136,7 +140,7 @@ void VariableStackPop(struct ParseState *Parser, struct Value *Var)
Success = HeapPopStack(Var, sizeof(struct Value)); /* free from heap */
}
else if (Var->ValOnStack)
Success = HeapPopStack(Var, sizeof(struct Value) + Var->Typ->Sizeof); /* free from stack */
Success = HeapPopStack(Var, sizeof(struct Value) + TypeSizeValue(Var)); /* free from stack */
else
Success = HeapPopStack(Var, sizeof(struct Value)); /* value isn't our problem */
@ -151,9 +155,12 @@ void VariableStackFrameAdd(struct ParseState *Parser, int NumParams)
HeapPushStackFrame();
NewFrame = HeapAllocStack(sizeof(struct StackFrame) + sizeof(struct Value *) * NumParams);
if (NewFrame == NULL)
ProgramFail(Parser, "out of memory");
NewFrame->ReturnParser = *Parser;
NewFrame->Parameter = (NumParams > 0) ? ((void *)NewFrame + sizeof(struct StackFrame)) : NULL;
TableInit(&NewFrame->LocalTable, &NewFrame->LocalHashTable[0], LOCAL_TABLE_SIZE, FALSE);
TableInitTable(&NewFrame->LocalTable, &NewFrame->LocalHashTable[0], LOCAL_TABLE_SIZE, FALSE);
NewFrame->PreviousStackFrame = TopStackFrame;
TopStackFrame = NewFrame;
}