Initial checkin of picoc. Not working yet.
git-svn-id: http://picoc.googlecode.com/svn/trunk@2 21eae674-98b7-11dd-bd71-f92a316d2d60
This commit is contained in:
parent
bc1b85ab0b
commit
7bfc2c0be5
22
Makefile
Normal file
22
Makefile
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
CC=gcc
|
||||||
|
CFLAGS=-Wall -g
|
||||||
|
|
||||||
|
TARGET = picoc
|
||||||
|
SRCS = picoc.c table.c str.c parse.c lex.c
|
||||||
|
OBJS := $(SRCS:%.c=%.o)
|
||||||
|
|
||||||
|
all: $(TARGET)
|
||||||
|
|
||||||
|
$(TARGET): $(OBJS)
|
||||||
|
$(CC) $(CFLAGS) -o $(TARGET) $(OBJS)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(TARGET) $(OBJS) *~
|
||||||
|
|
||||||
|
count:
|
||||||
|
wc $(SRCS) picoc.h
|
||||||
|
|
||||||
|
depend:
|
||||||
|
$(CC) -MM $(SRCS) >.depend
|
||||||
|
|
||||||
|
-include .depend
|
109
lex.c
Normal file
109
lex.c
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
#include "picoc.h"
|
||||||
|
|
||||||
|
#define LEXINC Lexer->Pos++
|
||||||
|
#define NEXTIS(c,x,y) { if (NextChar == (c)) { LEXINC; return (x); } else return (y); }
|
||||||
|
#define NEXTIS3(c,x,d,y,z) { if (NextChar == (c)) { LEXINC; return (x); } else NEXTIS(d,y,z) }
|
||||||
|
#define NEXTIS4(c,x,d,y,e,z,a) { if (NextChar == (c)) { LEXINC; return (x); } else NEXTIS3(d,y,e,z,a) }
|
||||||
|
|
||||||
|
struct ReservedWord
|
||||||
|
{
|
||||||
|
const char *Word;
|
||||||
|
enum LexToken Token;
|
||||||
|
};
|
||||||
|
|
||||||
|
static char *ReservedWords[] =
|
||||||
|
{
|
||||||
|
{ "char", TokenCharType },
|
||||||
|
{ "do", TokenDo },
|
||||||
|
{ "else", TokenElse },
|
||||||
|
{ "for", TokenFor },
|
||||||
|
{ "if", TokenIf },
|
||||||
|
{ "int", TokenIntType },
|
||||||
|
{ "while", TokenWhile },
|
||||||
|
{ "void", TokenVoidType }
|
||||||
|
};
|
||||||
|
|
||||||
|
void LexInit(struct LexState *Lexer, const Str *Source, int Line)
|
||||||
|
{
|
||||||
|
Lexer->Pos = Source->Str;
|
||||||
|
Lexer->End = Source->Str + Source->Len;
|
||||||
|
Lexer->Line = Line;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum LexToken LexCheckReservedWord(const Str *Word)
|
||||||
|
{
|
||||||
|
int Count;
|
||||||
|
|
||||||
|
for (Count = 0; Count < sizeof(ReservedWords) / sizeof(struct ReservedWord); Count++)
|
||||||
|
{
|
||||||
|
if (StrEqualC(Word, ReservedWord[Count].Word))
|
||||||
|
return ReservedWord[Count].Token;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TokenNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum LexToken LexGetNumber(struct LexState *Lexer)
|
||||||
|
{
|
||||||
|
XXX
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum LexToken LexGetWord(struct LexState *Lexer)
|
||||||
|
{
|
||||||
|
XXX
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum LexToken LexGetToken(struct LexState *Lexer)
|
||||||
|
{
|
||||||
|
char ThisChar;
|
||||||
|
char NextChar;
|
||||||
|
|
||||||
|
while (Lexer->Pos != Lexer->End && isspace(*Lexer->Pos))
|
||||||
|
Lexer->Pos++;
|
||||||
|
|
||||||
|
if (Lexer->Pos == Lexer->End)
|
||||||
|
return TokenEOF;
|
||||||
|
|
||||||
|
ThisChar = *Lexer->Pos;
|
||||||
|
if (isCidstart(ThisChar))
|
||||||
|
return LexGetWord(Lexer);
|
||||||
|
|
||||||
|
if (isdigit(ThisChar))
|
||||||
|
return LexGetNumber(Lexer);
|
||||||
|
|
||||||
|
NextChar = (Lexer->Pos+1 != Lexer->End) ? *(Lexer->Pos+1) : 0;
|
||||||
|
LEXINC;
|
||||||
|
switch (ThisChar)
|
||||||
|
{
|
||||||
|
case '"': return LexGetStringConstant(Lexer);
|
||||||
|
case '\'': return LexGetCharacterConstant(Lexer);
|
||||||
|
case '(': return TokenOpenBracket;
|
||||||
|
case ')': return TokenCloseBracket;
|
||||||
|
case '=': NEXTIS('=', TokenEquality, TokenAssignment);
|
||||||
|
case '+': NEXTIS3('=', TokenAddAssign, '+', TokenIncrement, TokenPlus);
|
||||||
|
case '-': NEXTIS4('=', TokenSubtractAssign, '>', TokenArrow, '-', TokenDecrement, TokenMinus);
|
||||||
|
case '*': return TokenAsterisk;
|
||||||
|
case '/': return TokenSlash;
|
||||||
|
case '<': NEXTIS('=', TokenLessEqual, TokenLess);
|
||||||
|
case '>': NEXTIS('=', TokenGreaterEqual, TokenGreater);
|
||||||
|
case ';': return TokenSemiColon;
|
||||||
|
case '&': NEXTIS('&', TokenLogicalAnd, TokenAmpersand);
|
||||||
|
case '|': NEXTIS('|', TokenLogicalOr, TokenArithmeticOr);
|
||||||
|
case '{': return TokenLeftBrace;
|
||||||
|
case '}': return TokenRightBrace;
|
||||||
|
case '[': return TokenLeftAngleBracket;
|
||||||
|
case ']': return TokenRightAngleBracket;
|
||||||
|
case '^': return TokenArithmeticExor;
|
||||||
|
case '~': return TokenUnaryExor;
|
||||||
|
case ',': return TokenComma;
|
||||||
|
case '.': return TokenDot;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgramError(Lexer->FileName, Lexer->Line, "illegal character '%c'", ThisChar);
|
||||||
|
return TokenEOF;
|
||||||
|
}
|
||||||
|
|
36
parse.c
Normal file
36
parse.c
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "picoc.h"
|
||||||
|
|
||||||
|
/* the table of global definitions */
|
||||||
|
struct Table GlobalTable;
|
||||||
|
struct TableEntry GlobalHashTable[GLOBAL_TABLE_SIZE];
|
||||||
|
|
||||||
|
|
||||||
|
void ParseInit()
|
||||||
|
{
|
||||||
|
TableInit(&GlobalTable, &GlobalHashTable[0], "global", GLOBAL_TABLE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* quick scan a source file for definitions */
|
||||||
|
void ParseScan(const Str *FileName, const Str *Source)
|
||||||
|
{
|
||||||
|
enum LexToken Token;
|
||||||
|
|
||||||
|
LexInit(Source);
|
||||||
|
|
||||||
|
while ( (Token = LexGetToken()) != TokenEOF)
|
||||||
|
{
|
||||||
|
/* do parsey things here */
|
||||||
|
printf("token %d\n", (int)Token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ParseCallFunction(const Str *FuncIdent, int argc, char **argv)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
90
picoc.c
Normal file
90
picoc.c
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "picoc.h"
|
||||||
|
|
||||||
|
/* all platform-dependent code is in this file */
|
||||||
|
|
||||||
|
void Fail(const char *Message, ...)
|
||||||
|
{
|
||||||
|
va_list Args;
|
||||||
|
|
||||||
|
va_start(Args, Message);
|
||||||
|
vprintf(Message, Args);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProgramError(const Str *FileName, int Line, const char *Message, ...)
|
||||||
|
{
|
||||||
|
va_list Args;
|
||||||
|
|
||||||
|
StrPrintf("%S:%d: ", FileName, Line)
|
||||||
|
va_start(Args, Message);
|
||||||
|
vprintf(Message, Args);
|
||||||
|
printf("\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read a file into memory. this is the only function using malloc().
|
||||||
|
* do it differently for embedded devices without malloc */
|
||||||
|
char *ReadFile(const Str *FileName)
|
||||||
|
{
|
||||||
|
struct stat FileInfo;
|
||||||
|
char *Text;
|
||||||
|
FILE *InFile;
|
||||||
|
char CFileName[PATH_MAX];
|
||||||
|
|
||||||
|
StrToC(CFileName, PATH_MAX, FileName);
|
||||||
|
|
||||||
|
if (stat(CFileName, &FileInfo))
|
||||||
|
Fail("can't read file %s\n", CFileName);
|
||||||
|
|
||||||
|
Text = malloc(FileInfo.st_size);
|
||||||
|
|
||||||
|
InFile = fopen(CFileName, "r");
|
||||||
|
if (InFile == NULL)
|
||||||
|
Fail("can't read file %s\n", CFileName);
|
||||||
|
|
||||||
|
if (fread(Text, 1, FileInfo.st_size, InFile) != FileInfo.st_size)
|
||||||
|
Fail("can't read file %s\n", CFileName);
|
||||||
|
|
||||||
|
fclose(InFile);
|
||||||
|
|
||||||
|
return Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read and scan a file for definitions */
|
||||||
|
void ScanFile(const Str *FileName)
|
||||||
|
{
|
||||||
|
char *Source;
|
||||||
|
Str SourceStr;
|
||||||
|
|
||||||
|
Source = ReadFile(FileName);
|
||||||
|
StrFromC(&SourceStr, Source);
|
||||||
|
ParseScan(FileName, &SourceStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
Str FileName;
|
||||||
|
Str StartFunc;
|
||||||
|
|
||||||
|
printf("picoc\n");
|
||||||
|
|
||||||
|
if (argc < 2)
|
||||||
|
Fail("Format: picoc <program.c> <args>...\n");
|
||||||
|
|
||||||
|
ParseInit();
|
||||||
|
|
||||||
|
StrFromC(&FileName, argv[1]);
|
||||||
|
ScanFile(&FileName);
|
||||||
|
|
||||||
|
StrFromC(&StartFunc, "main");
|
||||||
|
ParseCallFunction(&StartFunc, argc-1, &argv[1]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
144
picoc.h
Normal file
144
picoc.h
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
#ifndef PICOC_H
|
||||||
|
#define PICOC_H
|
||||||
|
|
||||||
|
/* configurable options */
|
||||||
|
#define USE_MALLOC
|
||||||
|
#define GLOBAL_TABLE_SIZE 199
|
||||||
|
|
||||||
|
/* handy definitions */
|
||||||
|
#ifndef TRUE
|
||||||
|
#define TRUE 1
|
||||||
|
#define FALSE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NULL
|
||||||
|
#define NULL 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef min
|
||||||
|
#define min(x,y) (((x)<(y))?(x):(y))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PATH_MAX
|
||||||
|
#define PATH_MAX 1024
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* lexical tokens */
|
||||||
|
enum LexToken
|
||||||
|
{
|
||||||
|
TokenNone,
|
||||||
|
TokenEOF,
|
||||||
|
TokenIdentifier,
|
||||||
|
TokenIntegerConstant,
|
||||||
|
TokenStringConstant,
|
||||||
|
TokenCharacterConstant,
|
||||||
|
TokenType,
|
||||||
|
TokenOpenBracket,
|
||||||
|
TokenCloseBracket,
|
||||||
|
TokenAssign,
|
||||||
|
TokenPlus,
|
||||||
|
TokenMinus,
|
||||||
|
TokenAsterisk,
|
||||||
|
TokenSlash,
|
||||||
|
TokenEquality,
|
||||||
|
TokenLessThan,
|
||||||
|
TokenGreaterThan,
|
||||||
|
TokenLessEqual,
|
||||||
|
TokenGreaterEqual,
|
||||||
|
TokenSemicolon,
|
||||||
|
TokenArrow,
|
||||||
|
TokenAmpersand,
|
||||||
|
TokenLeftBrace,
|
||||||
|
TokenRightBrace,
|
||||||
|
TokenLeftAngleBracket,
|
||||||
|
TokenRightAngleBracket,
|
||||||
|
TokenLogicalAnd,
|
||||||
|
TokenLogicalOr,
|
||||||
|
TokenArithmeticOr,
|
||||||
|
TokenArithmeticExor,
|
||||||
|
TokenUnaryExor,
|
||||||
|
TokenComma,
|
||||||
|
TokenDot,
|
||||||
|
TokenAddAssign,
|
||||||
|
TokenSubtractAssign,
|
||||||
|
TokenIncrement,
|
||||||
|
TokenDecrement,
|
||||||
|
TokenIntType,
|
||||||
|
TokenCharType,
|
||||||
|
TokenVoidType,
|
||||||
|
TokenDo,
|
||||||
|
TokenElse,
|
||||||
|
TokenFor,
|
||||||
|
TokenIf,
|
||||||
|
TokenWhile
|
||||||
|
};
|
||||||
|
|
||||||
|
/* string type so we can use source file strings */
|
||||||
|
typedef struct _Str
|
||||||
|
{
|
||||||
|
int Len;
|
||||||
|
const char *Str;
|
||||||
|
} Str;
|
||||||
|
|
||||||
|
|
||||||
|
/* hash table data structure */
|
||||||
|
struct TableEntry
|
||||||
|
{
|
||||||
|
Str Key;
|
||||||
|
void *Value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Table
|
||||||
|
{
|
||||||
|
const char *Name;
|
||||||
|
short Size;
|
||||||
|
struct TableEntry *HashTable;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* function definition - really just where it is in the source file */
|
||||||
|
struct FuncDef
|
||||||
|
{
|
||||||
|
Str Source;
|
||||||
|
Str FileName;
|
||||||
|
int StartLine;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* lexer state - so we can lex nested files */
|
||||||
|
struct LexState
|
||||||
|
{
|
||||||
|
int Line;
|
||||||
|
const char *Pos;
|
||||||
|
const char *End;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* str.c */
|
||||||
|
void StrToC(char *Dest, int DestSize, const Str *Source);
|
||||||
|
void StrFromC(Str *Dest, const char *Source);
|
||||||
|
int StrEqual(const Str *Str1, const Str *Str2);
|
||||||
|
int StrEqualC(const Str *Str1, const char *Str2);
|
||||||
|
void StrPrintf(const str *Format, ...);
|
||||||
|
|
||||||
|
/* picoc.c */
|
||||||
|
void Fail(const char *Message, ...);
|
||||||
|
void ProgramError(const Str *FileName, int Line, const char *Message, ...);
|
||||||
|
void ScanFile(const Str *FileName);
|
||||||
|
|
||||||
|
/* table.c */
|
||||||
|
void TableInit(struct Table *Tbl, struct TableEntry *HashTable, const char *Name, int Size);
|
||||||
|
void TableSet(struct Table *Tbl, const Str *Key, void *Value);
|
||||||
|
void *TableLookup(struct Table *Tbl, const Str *Key);
|
||||||
|
|
||||||
|
/* lex.c */
|
||||||
|
void LexInit(const Str *Source);
|
||||||
|
enum LexToken LexGetToken(void);
|
||||||
|
|
||||||
|
/* parse.c */
|
||||||
|
void ParseInit(void);
|
||||||
|
void ParseScan(const Str *FileName, const Str *Source);
|
||||||
|
void ParseCallFunction(const Str *FuncIdent, int argc, char **argv);
|
||||||
|
|
||||||
|
#endif /* PICOC_H */
|
||||||
|
|
55
str.c
Normal file
55
str.c
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "picoc.h"
|
||||||
|
|
||||||
|
|
||||||
|
void StrToC(char *Dest, int DestSize, const Str *Source)
|
||||||
|
{
|
||||||
|
int CopyLen = min(DestSize-1, Source->Len);
|
||||||
|
memcpy(Dest, Source->Str, CopyLen);
|
||||||
|
Dest[CopyLen] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void StrFromC(Str *Dest, const char *Source)
|
||||||
|
{
|
||||||
|
Dest->Str = Source;
|
||||||
|
Dest->Len = strlen(Source);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int StrEqual(const Str *Str1, const Str *Str2)
|
||||||
|
{
|
||||||
|
if (Str1->Len != Str2->Len)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return memcmp(Str1->Str, Str2->Str, Str1->Len) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int StrEqualC(const Str *Str1, const char *Str2)
|
||||||
|
{
|
||||||
|
return strncmp(Str1->Str, Str2, Str1->Len) == 0 && Str2[Str1->Len] == '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void StrPrintf(const str *Format, ...)
|
||||||
|
{
|
||||||
|
char FormatBuf[MAX_FORMAT];
|
||||||
|
const char *FPos;
|
||||||
|
char *BPos;
|
||||||
|
va_list Args;
|
||||||
|
|
||||||
|
va_start(Args, Format);
|
||||||
|
for (FPos = Format, BPos = &FormatBuf[0]; *FPos != '\0'; FPos++, BPos++)
|
||||||
|
{
|
||||||
|
if (*FPos == '%')
|
||||||
|
{
|
||||||
|
XXX
|
||||||
|
}
|
||||||
|
*BPos = *FPos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
122
table.c
Normal file
122
table.c
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "picoc.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef USE_MALLOC
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
|
static unsigned int TableHash(const Str *Key)
|
||||||
|
{
|
||||||
|
unsigned int Hash;
|
||||||
|
int Count;
|
||||||
|
int Offset;
|
||||||
|
const char *KeyPos;
|
||||||
|
|
||||||
|
Hash = Key->Len;
|
||||||
|
KeyPos = Key->Str;
|
||||||
|
Offset = 8;
|
||||||
|
for (Count = 0; Count < Key->Len; Count++, Offset+=7)
|
||||||
|
{
|
||||||
|
if (Offset > sizeof(unsigned int) * 8 - 7)
|
||||||
|
Offset -= (sizeof(unsigned int)-1) * 8;
|
||||||
|
|
||||||
|
Hash ^= *KeyPos++ << Offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TableInit(struct Table *Tbl, struct TableEntry *HashTable, const char *Name, int Size)
|
||||||
|
{
|
||||||
|
Tbl->Name = Name;
|
||||||
|
Tbl->Size = Size;
|
||||||
|
Tbl->HashTable = HashTable;
|
||||||
|
memset(HashTable, '\0', sizeof(struct TableEntry) * Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int TableCheckEntry(struct Table *Tbl, const Str *Key, int HashPos)
|
||||||
|
{
|
||||||
|
struct TableEntry *Entry = &Tbl->HashTable[HashPos];
|
||||||
|
|
||||||
|
if (Entry->Key.Len == 0)
|
||||||
|
return -1; /* empty */
|
||||||
|
|
||||||
|
else if (StrEqual(&Entry->Key, Key))
|
||||||
|
return HashPos; /* found */
|
||||||
|
|
||||||
|
else
|
||||||
|
return -2; /* wrong key */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int TableSearch(struct Table *Tbl, const Str *Key, int *AddAt)
|
||||||
|
{
|
||||||
|
int HashValue;
|
||||||
|
int HashPos;
|
||||||
|
int Result;
|
||||||
|
|
||||||
|
HashValue = TableHash(Key) % Tbl->Size;
|
||||||
|
|
||||||
|
for (HashPos = HashValue; HashPos < Tbl->Size; HashPos++)
|
||||||
|
{
|
||||||
|
*AddAt = HashPos;
|
||||||
|
if ( (Result = TableCheckEntry(Tbl, Key, HashPos)) != -2)
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (HashPos = 0; HashPos < HashValue; HashPos++)
|
||||||
|
{
|
||||||
|
*AddAt = HashPos;
|
||||||
|
if ( (Result = TableCheckEntry(Tbl, Key, HashPos)) != -2)
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* not found and table is full */
|
||||||
|
*AddAt = -1;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TableSet(struct Table *Tbl, const Str *Key, void *Value)
|
||||||
|
{
|
||||||
|
int HashPos;
|
||||||
|
int AddAt;
|
||||||
|
|
||||||
|
HashPos = TableSearch(Tbl, Key, &AddAt);
|
||||||
|
|
||||||
|
if (HashPos != -1)
|
||||||
|
Tbl->HashTable[HashPos].Value = Value; /* found - update value */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (AddAt == -1)
|
||||||
|
Fail("table '%s' is full\n", Tbl->Name);
|
||||||
|
|
||||||
|
else
|
||||||
|
{ /* add it to the table */
|
||||||
|
struct TableEntry *Entry = &Tbl->HashTable[AddAt];
|
||||||
|
Entry->Key = *Key;
|
||||||
|
Entry->Value = Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *TableLookup(struct Table *Tbl, const Str *Key)
|
||||||
|
{
|
||||||
|
int HashPos;
|
||||||
|
int AddAt;
|
||||||
|
|
||||||
|
HashPos = TableSearch(Tbl, Key, &AddAt);
|
||||||
|
|
||||||
|
if (HashPos == -1)
|
||||||
|
return NULL;
|
||||||
|
else
|
||||||
|
return Tbl->HashTable[HashPos].Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue