diff --git a/lex.c b/lex.c index 722e5e3..5cddd4a 100644 --- a/lex.c +++ b/lex.c @@ -236,6 +236,7 @@ enum LexToken LexGetStringConstant(struct LexState *Lexer, struct Value *Value) const char *EndPos; char *EscBuf; char *EscBufPos; + char *RegString; struct Value *ArrayValue; while (Lexer->Pos != Lexer->End && (*Lexer->Pos != '"' || Escape)) @@ -256,11 +257,21 @@ enum LexToken LexGetStringConstant(struct LexState *Lexer, struct Value *Value) for (EscBufPos = EscBuf, Lexer->Pos = StartPos; Lexer->Pos != EndPos;) *EscBufPos++ = LexUnEscapeCharacter(&Lexer->Pos, EndPos); - ArrayValue = VariableAllocValueAndData(NULL, sizeof(struct ArrayValue), FALSE, NULL, TRUE); - ArrayValue->Typ = CharArrayType; - ArrayValue->Val->Array.Size = EscBufPos - EscBuf + 1; - ArrayValue->Val->Array.Data = TableStrRegister2(EscBuf, EscBufPos - EscBuf); + /* try to find an existing copy of this string literal */ + RegString = TableStrRegister2(EscBuf, EscBufPos - EscBuf); HeapPopStack(EscBuf, EndPos - StartPos); + ArrayValue = VariableStringLiteralGet(RegString); + if (ArrayValue == NULL) + { + /* create and store this string literal */ + ArrayValue = VariableAllocValueAndData(NULL, sizeof(struct ArrayValue), FALSE, NULL, TRUE); + ArrayValue->Typ = CharArrayType; + ArrayValue->Val->Array.Size = EscBufPos - EscBuf + 1; + ArrayValue->Val->Array.Data = RegString; + VariableStringLiteralDefine(RegString, ArrayValue); + } + + /* create the the pointer for this char* */ Value->Typ = CharPtrType; Value->Val->Pointer.Segment = ArrayValue; Value->Val->Pointer.Data.Offset = 0; diff --git a/picoc.h b/picoc.h index 22c93cb..affd520 100644 --- a/picoc.h +++ b/picoc.h @@ -311,6 +311,8 @@ void VariableGet(struct ParseState *Parser, const char *Ident, struct Value **LV void VariableDefinePlatformVar(struct ParseState *Parser, char *Ident, struct ValueType *Typ, union AnyValue *FromValue, int IsWritable); void VariableStackFrameAdd(struct ParseState *Parser, int NumParams); void VariableStackFramePop(struct ParseState *Parser); +struct Value *VariableStringLiteralGet(char *Ident); +void VariableStringLiteralDefine(char *Ident, struct Value *Val); /* library.c */ void LibraryInit(struct Table *GlobalTable, const char *LibraryName, struct LibraryFunction (*FuncList)[]); diff --git a/platform.h b/platform.h index 6d02501..dfd1d75 100644 --- a/platform.h +++ b/platform.h @@ -13,8 +13,9 @@ #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 */ -#define GLOBAL_TABLE_SIZE 397 /* global variable table */ +#define GLOBAL_TABLE_SIZE 97 /* global variable table */ #define STRING_TABLE_SIZE 97 /* shared string table size */ +#define STRING_LITERAL_TABLE_SIZE 97 /* string literal table size */ #define PARAMETER_MAX 16 /* maximum number of parameters to a function */ #define LINEBUFFER_MAX 256 /* maximum number of characters on a line */ #define LOCAL_TABLE_SIZE 11 /* size of local variable table (can expand) */ diff --git a/variable.c b/variable.c index 102e6a5..d0a72ab 100644 --- a/variable.c +++ b/variable.c @@ -4,6 +4,10 @@ struct Table GlobalTable; struct TableEntry *GlobalHashTable[GLOBAL_TABLE_SIZE]; +/* the table of string literal values */ +struct Table StringLiteralTable; +struct TableEntry *StringLiteralHashTable[STRING_LITERAL_TABLE_SIZE]; + /* the stack */ struct StackFrame *TopStackFrame = NULL; @@ -12,20 +16,21 @@ struct StackFrame *TopStackFrame = NULL; void VariableInit() { TableInitTable(&GlobalTable, &GlobalHashTable[0], GLOBAL_TABLE_SIZE, TRUE); + TableInitTable(&StringLiteralTable, &StringLiteralHashTable[0], STRING_LITERAL_TABLE_SIZE, TRUE); TopStackFrame = NULL; } -/* deallocate the global table */ -void VariableCleanup() +/* deallocate the global table and the string literal table */ +void VariableTableCleanup(struct Table *HashTable) { struct TableEntry *Entry; struct TableEntry *NextEntry; struct Value *Val; int Count; - for (Count = 0; Count < GlobalTable.Size; Count++) + for (Count = 0; Count < HashTable->Size; Count++) { - for (Entry = GlobalTable.HashTable[Count]; Entry != NULL; Entry = NextEntry) + for (Entry = HashTable->HashTable[Count]; Entry != NULL; Entry = NextEntry) { NextEntry = Entry->Next; Val = Entry->p.v.Val; @@ -37,6 +42,12 @@ void VariableCleanup() } } +void VariableCleanup() +{ + VariableTableCleanup(&GlobalTable); + VariableTableCleanup(&StringLiteralTable); +} + /* allocate some memory, either on the heap or the stack and check if we've run out */ void *VariableAlloc(struct ParseState *Parser, int Size, int OnHeap) { @@ -216,3 +227,20 @@ void VariableStackFramePop(struct ParseState *Parser) TopStackFrame = TopStackFrame->PreviousStackFrame; HeapPopStackFrame(); } + +/* get a string literal. assumes that Ident is already registered. NULL if not found */ +struct Value *VariableStringLiteralGet(char *Ident) +{ + struct Value *LVal = NULL; + + if (TableGet(&StringLiteralTable, Ident, &LVal)) + return LVal; + else + return NULL; +} + +/* define a string literal. assumes that Ident is already registered */ +void VariableStringLiteralDefine(char *Ident, struct Value *Val) +{ + TableSet(&StringLiteralTable, Ident, Val); +}