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:
parent
2ac131247b
commit
4821d689ad
2
Makefile
2
Makefile
|
@ -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
11
TODO
|
@ -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
|
||||
|
|
178
intrinsic.c
178
intrinsic.c
|
@ -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
45
lex.c
|
@ -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
30
parse.c
|
@ -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
18
picoc.c
|
@ -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
50
picoc.h
|
@ -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
123
str.c
|
@ -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
35
table.c
|
@ -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
39
type.c
|
@ -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;
|
||||
|
||||
|
|
23
variable.c
23
variable.c
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue